Skip to content

Commit

Permalink
v0.1.5 service probe, version upgrade, and misc fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
geemus committed Oct 29, 2024
1 parent 531e84e commit 5b34c9a
Show file tree
Hide file tree
Showing 52 changed files with 1,989 additions and 235 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
shell: bash
run: echo 'flags=--skip homebrew' >> $GITHUB_ENV
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser-pro
version: latest
Expand Down Expand Up @@ -97,7 +97,7 @@ jobs:
enableCrossOsArchive: true

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser-pro
version: latest
Expand Down
40 changes: 40 additions & 0 deletions api/acme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package api

import (
"crypto/tls"
"encoding/base64"
"time"

"github.com/anchordotdev/cli"
"golang.org/x/crypto/acme"
"golang.org/x/crypto/acme/autocert"
)

func ProvisionCert(eab *Eab, domains []string, acmeURL string) (*tls.Certificate, error) {
hmacKey, err := base64.URLEncoding.DecodeString(eab.HmacKey)
if err != nil {
return nil, err
}

mgr := &autocert.Manager{
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(domains...),
Client: &acme.Client{
DirectoryURL: acmeURL,
UserAgent: cli.UserAgent(),
},
ExternalAccountBinding: &acme.ExternalAccountBinding{
KID: eab.Kid,
Key: hmacKey,
},
RenewBefore: 24 * time.Hour,
}

// TODO: switch to using ACME package here, so that extra domains can be sent through for SAN extension
clientHello := &tls.ClientHelloInfo{
ServerName: domains[0],
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
}

return mgr.GetCertificate(clientHello)
}
48 changes: 46 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ var (
ErrGnomeKeyringRequired = fmt.Errorf("gnome-keyring required for secure credential storage: %w", ErrSignedOut)
)

type QueryParam func(url.Values)

type QueryParams []QueryParam

func (q QueryParams) Apply(u *url.URL) {
val := u.Query()
for _, fn := range q {
fn(val)
}
u.RawQuery = val.Encode()
}

// NB: can't call this Client since the name is already taken by an openapi
// generated type. It's more like a session anyways, since it caches some
// current user info.
Expand Down Expand Up @@ -222,6 +234,34 @@ func (s *Session) FetchCredentials(ctx context.Context, orgSlug, realmSlug strin
return creds.Items, nil
}

func getCredentialsURL(orgSlug, realmSlug string) (*url.URL, error) {
return url.Parse(fetchCredentialsPath(orgSlug, realmSlug))
}

func SubCA(apid string) QueryParam {
return func(v url.Values) {
// TODO: v.Set("type", "subca")
v.Set("subject_uid_param", apid)
}
}

func (s *Session) GetCredentials(ctx context.Context, orgSlug, realmSlug string, params ...QueryParam) ([]Credential, error) {
var creds struct {
Items []Credential `json:"items,omitempty"`
}

u, err := getCredentialsURL(orgSlug, realmSlug)
if err != nil {
return nil, err
}
QueryParams(params).Apply(u)

if err := s.get(ctx, u.RequestURI(), &creds); err != nil {
return nil, err
}
return creds.Items, nil
}

func (s *Session) UserInfo(ctx context.Context) (*Root, error) {
if s.userInfo != nil {
return s.userInfo, nil
Expand Down Expand Up @@ -293,11 +333,14 @@ func (s *Session) GetService(ctx context.Context, orgSlug, serviceSlug string) (
return &svc, nil
}

func (s *Session) get(ctx context.Context, path string, out any) error {
req, err := http.NewRequestWithContext(ctx, "GET", path, nil)
func (s *Session) get(ctx context.Context, uri string, out any) error {
req, err := http.NewRequestWithContext(ctx, "GET", uri, nil)
if err != nil {
return err
}
if req.URL, err = url.Parse(uri); err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")

res, err := s.Do(req)
Expand Down Expand Up @@ -426,6 +469,7 @@ func (r urlRewriter) RoundTripper(next http.RoundTripper) http.RoundTripper {
if err != nil {
return nil, err
}
u.RawQuery = req.URL.RawQuery
req.URL = u.JoinPath(req.URL.Path)

return next.RoundTrip(req)
Expand Down
9 changes: 9 additions & 0 deletions api/openapi.gen.go

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

43 changes: 43 additions & 0 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/cli/browser"
"github.com/google/go-github/v54/github"
"github.com/mcuadros/go-defaults"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -41,10 +42,52 @@ var Version = struct {
Arch: runtime.GOARCH,
}

var LatestRelease *Release

type Release = github.RepositoryRelease

var SkipReleaseCheck = false

func IsDevVersion() bool {
return Version.Version == "dev"
}

func IsFreshLatestRelease(ctx context.Context) (bool, error) {
release, err := getLatestRelease(ctx)
if err != nil {
return true, err
}

return release.PublishedAt != nil && time.Since(release.PublishedAt.Time).Hours() < 24, nil
}

func IsUpgradeable(ctx context.Context) (bool, error) {
release, err := getLatestRelease(ctx)
if err != nil {
return false, err
}

return release.TagName != nil && *release.TagName != ReleaseTagName(), nil
}

func getLatestRelease(ctx context.Context) (*Release, error) {
if LatestRelease != nil {
return LatestRelease, nil
}

release, _, err := github.NewClient(nil).Repositories.GetLatestRelease(ctx, "anchordotdev", "cli")
if err != nil {
return nil, err
}

LatestRelease = &Release{
PublishedAt: release.PublishedAt,
TagName: release.TagName,
}

return LatestRelease, nil
}

func UserAgent() string {
return "Anchor CLI " + VersionString()
}
Expand Down
33 changes: 0 additions & 33 deletions cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"time"

"github.com/anchordotdev/cli"
"github.com/anchordotdev/cli/models"
"github.com/anchordotdev/cli/stacktrace"
_ "github.com/anchordotdev/cli/testflags"
"github.com/anchordotdev/cli/ui"
Expand Down Expand Up @@ -169,35 +168,3 @@ func (m *TestHint) View() string {
}

var Timestamp, _ = time.Parse(time.RFC3339Nano, "2024-01-02T15:04:05.987654321Z")

func TestConfigLoadTOMLGolden(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cfg := new(cli.Config)
cfg.File.Path = "anchor.toml"
cfg.Via.TOML = new(cli.Config)

ctx = cli.ContextWithConfig(ctx, cfg)

cmd := tomlCommand{}

uitest.TestTUIOutput(ctx, t, cmd.UI())
}

type tomlCommand struct{}

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

func (*tomlCommand) run(ctx context.Context, drv *ui.Driver) error {
cfg := cli.ConfigFromContext(ctx)
if cfg.Via.TOML != nil {
drv.Activate(ctx, models.ConfigLoaded(cfg.File.Path))
}

return nil
}
23 changes: 17 additions & 6 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"

"github.com/MakeNowJust/heredoc"
"github.com/anchordotdev/cli/models"
"github.com/anchordotdev/cli/stacktrace"
"github.com/anchordotdev/cli/ui"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -156,6 +155,13 @@ var rootDef = CmdDef{
Args: cobra.NoArgs,
Short: "Fetch Environment Variables for Service",
},
{
Name: "probe",

Use: "probe <service> [flags]",
Args: cobra.NoArgs,
Short: "Probe a service for proper TLS setup & configuration",
},
},
},
{
Expand Down Expand Up @@ -206,7 +212,16 @@ var rootDef = CmdDef{

Use: "version",
Args: cobra.NoArgs,
Short: "Show version info",
Short: "Show Version Info",
SubDefs: []CmdDef{
{
Name: "upgrade",

Use: "upgrade",
Args: cobra.NoArgs,
Short: "Check for Upgrade",
},
},
},
},
}
Expand Down Expand Up @@ -302,10 +317,6 @@ func NewCmd[T UIer](parent *cobra.Command, name string, fn func(*cobra.Command))
errc <- err
}()

if cfg.Via.TOML != nil {
drv.Activate(ctx, models.ConfigLoaded(cfg.File.Path))
}

if err := stacktrace.CapturePanic(func() error { return t.UI().RunTUI(ctx, drv) }); err != nil {
var uierr ui.Error
if errors.As(err, &uierr) {
Expand Down
Loading

0 comments on commit 5b34c9a

Please sign in to comment.