From 7d56f8919c5e3c91133426bf710dec5aeedc26b3 Mon Sep 17 00:00:00 2001 From: Yuval Shavit <110620369+yuval-klotho@users.noreply.github.com> Date: Wed, 1 Feb 2023 18:44:34 -0500 Subject: [PATCH] add `--local` auth This introduces a new Authorizer, which is hookable per KlothoMain. The default one just calls auth.Authorize(), but KlothoMains can provide an alternative, including one that adds flags. resolves #164 --- cmd/klotho/main.go | 18 ++++++++++++++++++ pkg/auth/auth.go | 27 ++++++++++++++++++++++++--- pkg/cli/klothomain.go | 26 ++++++++++++++++++++------ 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/cmd/klotho/main.go b/cmd/klotho/main.go index c4c88478b..0ad5a4e26 100644 --- a/cmd/klotho/main.go +++ b/cmd/klotho/main.go @@ -1,17 +1,35 @@ package main import ( + "github.com/klothoplatform/klotho/pkg/auth" "github.com/klothoplatform/klotho/pkg/cli" + "github.com/spf13/pflag" ) func main() { + authRequirement := LocalAuth(false) km := cli.KlothoMain{ DefaultUpdateStream: "open:latest", Version: Version, PluginSetup: func(psb *cli.PluginSetBuilder) error { return psb.AddAll() }, + Authorizer: &authRequirement, } km.Main() } + +// LocalAuth is an auth.Authorizer that requires login unless its value is true. +type LocalAuth bool + +func (local *LocalAuth) SetUpCliFlags(flags *pflag.FlagSet) { + flags.BoolVar((*bool)(local), "local", bool(*local), "If provided, runs Klotho with a local login (that is, not requiring an authenticated login)") +} + +func (local *LocalAuth) Authorize() error { + if !*local { + return auth.Authorize() + } + return nil +} diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index b071f6342..cb80ef67a 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -22,6 +22,23 @@ type LoginResponse struct { State string } +type Authorizer interface { + Authorize() error +} + +func DefaultIfNil(auth Authorizer) Authorizer { + if auth == nil { + return standardAuthorizer{} + } + return auth +} + +type standardAuthorizer struct{} + +func (s standardAuthorizer) Authorize() error { + return Authorize() +} + func Login() error { state, err := CallLoginEndpoint() if err != nil { @@ -126,7 +143,11 @@ type MyCustomClaims struct { jwt.StandardClaims } -func Authorize(tokenRefreshed bool) error { +func Authorize() error { + return authorize(false) +} + +func authorize(tokenRefreshed bool) error { creds, err := GetIDToken() if err != nil { return errors.New("failed to get credentials for user, please login") @@ -147,7 +168,7 @@ func Authorize(tokenRefreshed bool) error { if err != nil { return err } - err = Authorize(true) + err = authorize(true) if err != nil { return err } @@ -161,7 +182,7 @@ func Authorize(tokenRefreshed bool) error { if err != nil { return err } - err = Authorize(true) + err = authorize(true) if err != nil { return err } diff --git a/pkg/cli/klothomain.go b/pkg/cli/klothomain.go index d8cf6e15a..c00c24dc0 100644 --- a/pkg/cli/klothomain.go +++ b/pkg/cli/klothomain.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "github.com/spf13/pflag" "os" "regexp" @@ -29,6 +30,12 @@ type KlothoMain struct { Version string VersionQualifier string PluginSetup func(*PluginSetBuilder) error + // Authorizer is an optional authorizer override. If this also conforms to FlagsProvider, those flags will be added. + Authorizer auth.Authorizer +} + +type FlagsProvider interface { + SetUpCliFlags(flags *pflag.FlagSet) } var cfg struct { @@ -71,6 +78,7 @@ const ( ) func (km KlothoMain) Main() { + km.Authorizer = auth.DefaultIfNil(km.Authorizer) var root = &cobra.Command{ Use: "klotho [path to source]", @@ -94,8 +102,13 @@ func (km KlothoMain) Main() { flags.BoolVar(&cfg.version, "version", false, "Print the version") flags.BoolVar(&cfg.update, "update", false, "update the cli to the latest version") flags.StringToStringVar(&cfg.setOption, "set-option", nil, "Sets a CLI option") - flags.BoolVar(&cfg.login, "login", false, "Login to Klotho with email. For anonymous login, use 'local'") + flags.BoolVar(&cfg.login, "login", false, "Login to Klotho with email.") flags.BoolVar(&cfg.logout, "logout", false, "Logout of current klotho account.") + + if authFlags, hasFlags := km.Authorizer.(FlagsProvider); hasFlags { + authFlags.SetUpCliFlags(flags) + } + _ = flags.MarkHidden("internalDebug") err := root.Execute() @@ -205,11 +218,6 @@ func (km KlothoMain) run(cmd *cobra.Command, args []string) (err error) { return nil } - err = auth.Authorize(false) - if err != nil { - return err - - } // Set up analytics analyticsClient, err := analytics.NewClient(map[string]interface{}{ "version": km.Version, @@ -253,6 +261,12 @@ func (km KlothoMain) run(cmd *cobra.Command, args []string) (err error) { analyticsClient.Properties[km.VersionQualifier] = true } + // Needs to go after the --version and --update checks + err = km.Authorizer.Authorize() + if err != nil { + return err + } + // if update is specified do the update in place var klothoUpdater = updater.Updater{ ServerURL: updater.DefaultServer,