Skip to content

Commit

Permalink
v0.0.13: lcl clean and misc refinements
Browse files Browse the repository at this point in the history
  • Loading branch information
geemus committed Mar 14, 2024
1 parent b077124 commit 8a04355
Show file tree
Hide file tree
Showing 22 changed files with 655 additions and 330 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Anchor
Copyright (c) 2024 Anchor

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Anchor CLI

`anchor` is a command line interface for the [Anchor.dev](https://anchor.dev) certificate management platform.

## Installation

### macOS

`anchor` is available via [Homebrew][] or as a downloadable binary from the [releases page][].

#### Homebrew

| Install: | Upgrade: |
| -------------------------------------- | -------------------------------------- |
| `brew install anchordotdev/tap/anchor` | `brew upgrade anchordotdev/tap/anchor` |

### Linux & BSD

`anchor` is available via [Homebrew][] or as a downloadable binary from the [releases page][].

#### Homebrew

| Install: | Upgrade: |
| -------------------------------------- | -------------------------------------- |
| `brew install anchordotdev/tap/anchor` | `brew upgrade anchordotdev/tap/anchor` |

### Windows

`anchor` is not yet supported.

### Install from source

To install `anchor` from source run `go install github.com/anchordotdev/cli/cmd/anchor@latest`.

[Homebrew]: https://brew.sh
[releases page]: https://github.com/anchordotdev/cli/releases/latest
7 changes: 4 additions & 3 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,11 @@ func (s *Session) CreateEAB(ctx context.Context, chainSlug, orgSlug, realmSlug,
return &eabOutput, nil
}

func (s *Session) CreateService(ctx context.Context, orgSlug, serverType, serviceSlug string) (*Service, error) {
func (s *Session) CreateService(ctx context.Context, orgSlug, serviceSlug, serverType string, localhostPort *int) (*Service, error) {
serviceInput := CreateServiceJSONRequestBody{
Name: serviceSlug,
ServerType: serverType,
Name: serviceSlug,
ServerType: serverType,
LocalhostPort: localhostPort,
}
serviceInput.Relationships.Organization.Slug = orgSlug

Expand Down
8 changes: 6 additions & 2 deletions api/openapi.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type Config struct {
Audit struct {
} `cmd:"audit"`

Clean struct {
} `cmd:"clean"`

Config struct {
} `cmd:"config"`

Expand Down
23 changes: 17 additions & 6 deletions cmd/anchor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (
"os"

"github.com/MakeNowJust/heredoc"
"github.com/atotto/clipboard"
"github.com/google/go-github/v54/github"

"github.com/anchordotdev/cli"
"github.com/anchordotdev/cli/auth"
"github.com/anchordotdev/cli/lcl"
"github.com/anchordotdev/cli/trust"
"github.com/anchordotdev/cli/ui"
)

var (
Expand Down Expand Up @@ -87,6 +89,13 @@ var (
Use: "audit",
Short: "Audit lcl.host HTTPS Local Development Environment",
},
{
UI: lcl.LclClean{Config: cfg}.UI(),

Name: "clean",
Use: "clean",
Short: "Clean lcl.host CA Certificates from the Local Trust Store(s)",
},
{
UI: lcl.LclConfig{Config: cfg}.UI(),

Expand Down Expand Up @@ -152,12 +161,8 @@ var (

Name: "clean",
Use: "clean TODO",
Short: "clean the Local trust store(s)",
Short: "Clean CA Certificates from the Local Trust Store(s)",
Hidden: true,

Long: heredoc.Doc(`
TODO
`),
},
},
},
Expand Down Expand Up @@ -194,7 +199,13 @@ func versionCheck(ctx context.Context) error {
return err
}
if release.TagName == nil || *release.TagName != "v"+version {
return fmt.Errorf("anchor CLI v%s is out of date, run `brew upgrade anchordotdev/tap/anchor` to install the latest", version)
fmt.Println(ui.StepHint(fmt.Sprintf("Your anchor CLI v%s is out of date, please update before running other commands.", version)))
if err := clipboard.WriteAll("brew upgrade anchordotdev/tap/anchor"); err == nil {
fmt.Println(ui.StepAlert(fmt.Sprintf("Copied %s to your clipboard.", ui.Announce("brew upgrade anchordotdev/tap/anchor"))))
}
fmt.Println(ui.StepAlert(fmt.Sprintf("%s `%s` to update to the latest version.", ui.Action("Run"), ui.Emphasize("brew upgrade anchordotdev/tap/anchor"))))
fmt.Println(ui.StepHint(fmt.Sprintf("Not using homebrew? Explore other options here: %s", ui.URL("https://github.com/anchordotdev/cli"))))
return fmt.Errorf("anchor CLI version update required")
}
return nil
}
70 changes: 70 additions & 0 deletions lcl/clean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package lcl

import (
"context"

"github.com/anchordotdev/cli"
"github.com/anchordotdev/cli/api"
"github.com/anchordotdev/cli/auth"
"github.com/anchordotdev/cli/lcl/models"
"github.com/anchordotdev/cli/trust"
"github.com/anchordotdev/cli/ui"
)

type LclClean struct {
Config *cli.Config

anc *api.Session
orgSlug, realmSlug string
}

func (c LclClean) UI() cli.UI {
return cli.UI{
RunTUI: c.run,
}
}

func (c LclClean) run(ctx context.Context, drv *ui.Driver) error {
var err error
clientCmd := &auth.Client{
Config: c.Config,
Anc: c.anc,
}
c.anc, err = clientCmd.Perform(ctx, drv)
if err != nil {
return err
}

c.Config.Trust.Clean.States = []string{"all"}

if c.orgSlug == "" {
userInfo, err := c.anc.UserInfo(ctx)
if err != nil {
return err
}
c.orgSlug = userInfo.PersonalOrg.Slug
}

if c.realmSlug == "" {
c.realmSlug = "localhost"
}

drv.Activate(ctx, &models.LclCleanHeader{})
drv.Activate(ctx, &models.LclCleanHint{
TrustStores: c.Config.Trust.Stores,
})

cmd := &trust.Clean{
Config: c.Config,
Anc: c.anc,
OrgSlug: c.orgSlug,
RealmSlug: c.realmSlug,
}

err = cmd.Perform(ctx, drv)
if err != nil {
return err
}

return nil
}
41 changes: 38 additions & 3 deletions lcl/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package lcl
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/url"
"slices"
"strconv"
"strings"

"github.com/cli/browser"

Expand All @@ -17,6 +21,8 @@ import (
"github.com/anchordotdev/cli/ui"
)

var loopbackAddrs = []string{"127.0.0.1", "::1"}

type LclConfig struct {
Config *cli.Config

Expand Down Expand Up @@ -76,15 +82,38 @@ func (c LclConfig) perform(ctx context.Context, drv *ui.Driver) error {
InputCh: inputc,
Default: "hi-" + c.orgSlug,
TLD: "lcl.host",
Prompt: "What lcl.host domain would you like to use for diagnostics?",
Done: "Entered %s domain for lcl.host diagnostic certificate.",
})

var serviceName string
var lclDomain string
select {
case serviceName = <-inputc:
case lclDomain = <-inputc:
case <-ctx.Done():
return ctx.Err()
}

serviceName := strings.TrimSuffix(lclDomain, ".lcl.host")

drv.Activate(ctx, &models.DomainResolver{
Domain: lclDomain,
})

addrs, err := new(net.Resolver).LookupHost(ctx, lclDomain)
if err != nil {
drv.Send(models.DomainStatusMsg(false))
return err
}

for _, addr := range addrs {
if !slices.Contains(loopbackAddrs, addr) {
drv.Send(models.DomainStatusMsg(false))

return fmt.Errorf("%s domain resolved to non-loopback interface address: %s", lclDomain, addr)
}
}
drv.Send(models.DomainStatusMsg(true))

domains := []string{serviceName + ".lcl.host", serviceName + ".localhost"}

cmdProvision := &Provision{
Expand All @@ -94,7 +123,13 @@ func (c LclConfig) perform(ctx context.Context, drv *ui.Driver) error {
realmSlug: c.realmSlug,
}

_, cert, err := cmdProvision.run(ctx, drv, c.anc, serviceName, "diagnostic")
var localhostPort int
localhostPort, err = strconv.Atoi(diagPort)
if err != nil {
return err
}

_, cert, err := cmdProvision.run(ctx, drv, c.anc, serviceName, "diagnostic", &localhostPort)
if err != nil {
return err
}
Expand Down
49 changes: 49 additions & 0 deletions lcl/models/clean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package models

import (
"fmt"
"strings"

"github.com/anchordotdev/cli/ui"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
)

type LclCleanHeader struct{}

func (LclCleanHeader) Init() tea.Cmd { return nil }

func (m *LclCleanHeader) Update(tea.Msg) (tea.Model, tea.Cmd) { return m, nil }

func (m *LclCleanHeader) View() string {
var b strings.Builder
fmt.Fprintln(&b, ui.Header(fmt.Sprintf("Clean lcl.host CA Certificates from Local Trust Store(s) %s", ui.Whisper("`anchor trust clean`"))))
return b.String()
}

type LclCleanHint struct {
TrustStores []string

spinner spinner.Model
}

func (c *LclCleanHint) Init() tea.Cmd {
c.spinner = ui.WaitingSpinner()

return c.spinner.Tick
}

func (c *LclCleanHint) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
c.spinner, cmd = c.spinner.Update(msg)
return c, cmd
}

func (c *LclCleanHint) View() string {
stores := strings.Join(c.TrustStores, ", ")

var b strings.Builder
fmt.Fprintln(&b, ui.Hint(fmt.Sprintf("Removing lcl.host CA certificates from the %s store(s).", stores)))

return b.String()
}
Loading

0 comments on commit 8a04355

Please sign in to comment.