-
Notifications
You must be signed in to change notification settings - Fork 281
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Grant Linville <[email protected]>
- Loading branch information
1 parent
a1b26c3
commit f4284f4
Showing
25 changed files
with
927 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Credentials | ||
|
||
GPTScript supports credential provider tools. These tools can be used to fetch credentials from a secure location (or | ||
directly from user input) and conveniently set them in the environment before running a script. | ||
|
||
## Writing a Credential Provider Tool | ||
|
||
A credential provider tool looks just like any other GPTScript, with the following caveats: | ||
- It cannot call the LLM and must run a command. | ||
- It must print contents to stdout in the format `{"env":{"ENV_VAR_1":"value1","ENV_VAR_2":"value2"}}`. | ||
- Any args defined on the tool will be ignored. | ||
|
||
Here is a simple example of a credential provider tool that uses the builtin `sys.prompt` to ask the user for some input: | ||
|
||
```yaml | ||
# my-credential-tool.gpt | ||
name: my-credential-tool | ||
|
||
#!/usr/bin/env bash | ||
|
||
output=$(gptscript -q --cache=false sys.prompt '{"message":"Please enter your fake credential.","fields":"credential","sensitive":"true"}') | ||
credential=$(echo $output | jq -r '.credential') | ||
echo "{\"env\":{\"MY_ENV_VAR\":\"$credential\"}}" | ||
``` | ||
|
||
## Using a Credential Provider Tool | ||
|
||
Continuing with the above example, this is how you can use it in a script: | ||
|
||
```yaml | ||
credentials: my-credential-tool.gpt | ||
|
||
#!/usr/bin/env bash | ||
|
||
echo "The value of MY_ENV_VAR is $MY_ENV_VAR" | ||
``` | ||
|
||
When you run the script, GPTScript will call the credential provider tool first, set the environment variables from its | ||
output, and then run the script body. The credential provider tool is called by GPTScript itself. GPTScript does not ask the | ||
LLM about it or even tell the LLM about the tool. | ||
|
||
If GPTScript has called the credential provider tool in the same context (more on that later), then it will use the stored | ||
credential instead of fetching it again. | ||
|
||
You can also specify multiple credential tools for the same script: | ||
|
||
```yaml | ||
credentials: credential-tool-1.gpt, credential-tool-2.gpt | ||
|
||
(tool stuff here) | ||
``` | ||
|
||
## Storing Credentials | ||
|
||
By default, credentials are automatically stored in a config file at `$XDG_CONFIG_HOME/gptscript/config.json`. | ||
This config file also has another parameter, `credsStore`, which indicates where the credentials are being stored. | ||
|
||
- `file` (default): The credentials are stored directly in the config file. | ||
- `osxkeychain`: The credentials are stored in the macOS Keychain. | ||
|
||
In order to use `osxkeychain` as the credsStore, you must have the `gptscript-credential-osxkeychain` executable | ||
available in your PATH. There will probably be better packaging for this in the future, but for now, you can build it | ||
from the [repo](https://github.com/gptscript-ai/gptscript-credential-helpers). | ||
|
||
There will likely be support added for other credential stores in the future. | ||
|
||
:::note | ||
Credentials received from credential provider tools that are not on GitHub (such as a local file) will not be stored | ||
in the credentials store. | ||
::: | ||
|
||
## Credential Contexts | ||
|
||
Each stored credential is uniquely identified by the name of its provider tool and the name of its context. A credential | ||
context is basically a namespace for credentials. If you have multiple credentials from the same provider tool, you can | ||
switch between them by defining them in different credential contexts. The default context is called `default`, and this | ||
is used if none is specified. | ||
|
||
You can set the credential context to use with the `--credential-context` flag when running GPTScript. For | ||
example: | ||
|
||
```bash | ||
gptscript --credential-context my-azure-workspace my-azure-script.gpt | ||
``` | ||
|
||
Any credentials fetched for that script will be stored in the `my-azure-workspace` context. If you were to call it again | ||
with a different context, you would be able to give it a different set of credentials. | ||
|
||
## Listing and Deleting Stored Credentials | ||
|
||
The `gptscript credential` command can be used to list and delete stored credentials. Running the command with no | ||
`--credential-context` set will use the `default` credential context. You can also specify that it should list | ||
credentials in all contexts with `--all-contexts`. | ||
|
||
You can delete a credential by running the following command: | ||
|
||
```bash | ||
gptscript credential delete --credential-context <credential context> <credential tool name> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"sort" | ||
"text/tabwriter" | ||
|
||
cmd2 "github.com/acorn-io/cmd" | ||
"github.com/gptscript-ai/gptscript/pkg/config" | ||
"github.com/gptscript-ai/gptscript/pkg/credentials" | ||
"github.com/gptscript-ai/gptscript/pkg/version" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type Credential struct { | ||
root *GPTScript | ||
AllContexts bool `usage:"List credentials for all contexts" local:"true"` | ||
} | ||
|
||
func (c *Credential) Customize(cmd *cobra.Command) { | ||
cmd.Use = "credential" | ||
cmd.Version = version.Get().String() | ||
cmd.Aliases = []string{"cred", "creds", "credentials"} | ||
cmd.Short = "List stored credentials" | ||
cmd.Args = cobra.NoArgs | ||
cmd.AddCommand(cmd2.Command(&Delete{root: c.root})) | ||
} | ||
|
||
func (c *Credential) Run(_ *cobra.Command, _ []string) error { | ||
cfg, err := config.ReadCLIConfig(c.root.ConfigFile) | ||
if err != nil { | ||
return fmt.Errorf("failed to read CLI config: %w", err) | ||
} | ||
|
||
ctx := c.root.CredentialContext | ||
if c.AllContexts { | ||
ctx = "*" | ||
} | ||
|
||
store, err := credentials.NewStore(cfg, ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to get credentials store: %w", err) | ||
} | ||
|
||
creds, err := store.List() | ||
if err != nil { | ||
return fmt.Errorf("failed to list credentials: %w", err) | ||
} | ||
|
||
if c.AllContexts { | ||
// Sort credentials by context | ||
sort.Slice(creds, func(i, j int) bool { | ||
if creds[i].Context == creds[j].Context { | ||
return creds[i].ToolName < creds[j].ToolName | ||
} | ||
return creds[i].Context < creds[j].Context | ||
}) | ||
|
||
w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0) | ||
defer w.Flush() | ||
_, _ = w.Write([]byte("CONTEXT\tTOOL\n")) | ||
for _, cred := range creds { | ||
_, _ = fmt.Fprintf(w, "%s\t%s\n", cred.Context, cred.ToolName) | ||
} | ||
} else { | ||
// Sort credentials by tool name | ||
sort.Slice(creds, func(i, j int) bool { | ||
return creds[i].ToolName < creds[j].ToolName | ||
}) | ||
|
||
for _, cred := range creds { | ||
fmt.Println(cred.ToolName) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/gptscript-ai/gptscript/pkg/config" | ||
"github.com/gptscript-ai/gptscript/pkg/credentials" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type Delete struct { | ||
root *GPTScript | ||
} | ||
|
||
func (c *Delete) Customize(cmd *cobra.Command) { | ||
cmd.Use = "delete <tool name>" | ||
cmd.SilenceUsage = true | ||
cmd.Short = "Delete a stored credential" | ||
cmd.Args = cobra.ExactArgs(1) | ||
} | ||
|
||
func (c *Delete) Run(_ *cobra.Command, args []string) error { | ||
cfg, err := config.ReadCLIConfig(c.root.ConfigFile) | ||
if err != nil { | ||
return fmt.Errorf("failed to read CLI config: %w", err) | ||
} | ||
|
||
store, err := credentials.NewStore(cfg, c.root.CredentialContext) | ||
if err != nil { | ||
return fmt.Errorf("failed to get credentials store: %w", err) | ||
} | ||
|
||
if err = store.Remove(args[0]); err != nil { | ||
return fmt.Errorf("failed to remove credential: %w", err) | ||
} | ||
return nil | ||
} |
Oops, something went wrong.