From bc5fb88a313d816efae01ae69dc0d9f674a6be63 Mon Sep 17 00:00:00 2001 From: Donnie Adams Date: Thu, 21 Nov 2024 10:21:02 -0500 Subject: [PATCH 1/2] fix: allow listing of credentials in all contexts Signed-off-by: Donnie Adams --- pkg/cli/credential.go | 8 +++++++- pkg/credentials/store.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/cli/credential.go b/pkg/cli/credential.go index eaf7665b..866ed4e5 100644 --- a/pkg/cli/credential.go +++ b/pkg/cli/credential.go @@ -9,6 +9,7 @@ import ( "time" cmd2 "github.com/gptscript-ai/cmd" + "github.com/gptscript-ai/gptscript/pkg/credentials" "github.com/gptscript-ai/gptscript/pkg/gptscript" "github.com/spf13/cobra" ) @@ -44,7 +45,12 @@ func (c *Credential) Run(cmd *cobra.Command, _ []string) error { } defer gptScript.Close(true) - store, err := gptScript.CredentialStoreFactory.NewStore(gptScript.DefaultCredentialContexts) + credCtxs := gptScript.DefaultCredentialContexts + if c.AllContexts { + credCtxs = []string{credentials.AllCredentialContexts} + } + + store, err := gptScript.CredentialStoreFactory.NewStore(credCtxs) if err != nil { return err } diff --git a/pkg/credentials/store.go b/pkg/credentials/store.go index b839ad6d..be4be183 100644 --- a/pkg/credentials/store.go +++ b/pkg/credentials/store.go @@ -140,7 +140,7 @@ func (s Store) List(_ context.Context) ([]Credential, error) { } if len(s.credCtxs) > 0 && s.credCtxs[0] == AllCredentialContexts { - allCreds := make([]Credential, len(list)) + allCreds := make([]Credential, 0, len(list)) for serverAddress := range list { ac, err := store.Get(serverAddress) if err != nil { From c91ac71419f70540c09313c3eb4e3b9e0e04196c Mon Sep 17 00:00:00 2001 From: Donnie Adams Date: Thu, 21 Nov 2024 10:23:12 -0500 Subject: [PATCH 2/2] fix: reload CLI config when getting credentials When running in SDK server mode and using the file cred store, we must reload the credentials in the file each time. Typically, these credentials will be added via a tool call, which would invalidate the credentials held in memory. Signed-off-by: Donnie Adams --- pkg/config/cliconfig.go | 47 +++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/pkg/config/cliconfig.go b/pkg/config/cliconfig.go index 73741ab3..d7944d8e 100644 --- a/pkg/config/cliconfig.go +++ b/pkg/config/cliconfig.go @@ -11,6 +11,7 @@ import ( "github.com/adrg/xdg" "github.com/docker/cli/cli/config/types" + "github.com/gptscript-ai/gptscript/pkg/mvl" ) const ( @@ -24,6 +25,7 @@ const ( var ( // Helpers is a list of all supported credential helpers from github.com/gptscript-ai/gptscript-credential-helpers Helpers = []string{WincredCredHelper, OsxkeychainCredHelper, SecretserviceCredHelper, PassCredHelper} + log = mvl.Package() ) type AuthConfig types.AuthConfig @@ -85,9 +87,9 @@ func (c *CLIConfig) Save() error { } if c.auths != nil { - c.Auths = map[string]AuthConfig{} + c.Auths = make(map[string]AuthConfig, len(c.auths)) for k, v := range c.auths { - c.Auths[k] = (AuthConfig)(v) + c.Auths[k] = AuthConfig(v) } c.auths = nil } @@ -116,13 +118,21 @@ func (c *CLIConfig) GetAuthConfigs() map[string]types.AuthConfig { defer c.authsLock.Unlock() } + if err := c.readFileIntoConfig(c.location); err != nil { + // This is implementing an interface, so we can't return this error. + log.Warnf("Failed to read config file: %v", err) + } + if c.auths == nil { - c.auths = map[string]types.AuthConfig{} - for k, v := range c.Auths { - authConfig := (types.AuthConfig)(v) - c.auths[k] = authConfig - } + c.auths = make(map[string]types.AuthConfig, len(c.Auths)) + } + + // Assume that whatever was pulled from the file is more recent. + // The docker creds framework will save the file after creating or updating a credential. + for k, v := range c.Auths { + c.auths[k] = types.AuthConfig(v) } + return c.auths } @@ -142,17 +152,13 @@ func ReadCLIConfig(gptscriptConfigFile string) (*CLIConfig, error) { } } - data, err := readFile(gptscriptConfigFile) - if err != nil { - return nil, err - } result := &CLIConfig{ authsLock: &sync.Mutex{}, location: gptscriptConfigFile, - raw: data, } - if err := json.Unmarshal(data, result); err != nil { - return nil, fmt.Errorf("failed to unmarshal %s: %v", gptscriptConfigFile, err) + + if err := result.readFileIntoConfig(gptscriptConfigFile); err != nil { + return nil, err } if store := os.Getenv("GPTSCRIPT_CREDENTIAL_STORE"); store != "" { @@ -180,13 +186,18 @@ func (c *CLIConfig) setDefaultCredentialsStore() error { return c.Save() } -func readFile(path string) ([]byte, error) { +func (c *CLIConfig) readFileIntoConfig(path string) error { data, err := os.ReadFile(path) if os.IsNotExist(err) { - return []byte("{}"), nil + return nil } else if err != nil { - return nil, fmt.Errorf("failed to read user config %s: %w", path, err) + return fmt.Errorf("failed to read user config %s: %w", path, err) } - return data, nil + c.raw = data + if err := json.Unmarshal(data, c); err != nil { + return fmt.Errorf("failed to unmarshal %s: %v", path, err) + } + + return nil }