Documentation
¶
Overview ¶
Package credential provides credential management for Moat.
Package credential provides credential management for Moat.
Package credential provides secure credential storage and retrieval.
Package credential provides secure credential storage and retrieval.
Index ¶
- Constants
- func DefaultEncryptionKey() ([]byte, error)
- func DefaultStoreDir() string
- func GenerateAccessTokenPlaceholder(accountID string) string
- func GenerateIDTokenPlaceholder(accountID string) string
- func ImpliedDependencies(grants []string) []string
- func IsKnownProvider(p Provider) bool
- func IsOAuthToken(token string) bool
- func RegisterImpliedDeps(provider Provider, fn func() []string)
- func RegisterProviderSetup(provider Provider, setup ProviderSetup)
- func ValidateGrant(grant string) error
- type AnthropicAuth
- type ClaudeCodeCredentials
- type ClaudeOAuthCredentials
- type ClaudeOAuthToken
- type Credential
- type FileStore
- func (s *FileStore) AddSSHMapping(mapping SSHMapping) error
- func (s *FileStore) Delete(provider Provider) error
- func (s *FileStore) Get(provider Provider) (*Credential, error)
- func (s *FileStore) GetSSHMappings() ([]SSHMapping, error)
- func (s *FileStore) GetSSHMappingsForHosts(hosts []string) ([]SSHMapping, error)
- func (s *FileStore) List() ([]Credential, error)
- func (s *FileStore) RemoveSSHMapping(host string) error
- func (s *FileStore) Save(cred Credential) error
- type OAuthCredentialInfo
- type OpenAIAuth
- type Provider
- type ProviderCredential
- type ProviderResult
- type ProviderSetup
- type ProxyConfigurer
- type ResponseTransformer
- type SSHMapping
- type Store
Constants ¶
const ( // ClaudeCodeKeychainService is the macOS Keychain service name for Claude Code credentials. ClaudeCodeKeychainService = "Claude Code-credentials" // ClaudeCredentialsFile is the relative path to Claude's credentials file. ClaudeCredentialsFile = ".claude/.credentials.json" )
const GitHubTokenPlaceholder = "ghp_moatProxyInjectedPlaceholder000000000000"
GitHubTokenPlaceholder is a placeholder that looks like a valid GitHub personal access token.
The gh CLI validates token format locally before making requests. Real GitHub PATs use the format ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (ghp_ prefix + 36 base62 characters, 40 total).
This format-valid placeholder is necessary because: - gh CLI checks GH_TOKEN format before making API calls - Tools like Claude Code's footer use gh CLI to fetch PR status - Without a valid-looking token, gh CLI rejects it and may prompt for auth
The proxy intercepts all GitHub HTTPS traffic and injects the real token via Authorization headers, so this placeholder never reaches GitHub's servers.
const JWTPlaceholder = "" /* 135-byte string literal not displayed */
JWTPlaceholder is a basic placeholder JWT for format validation only. Use GenerateIDTokenPlaceholder for Codex CLI which needs account_id in claims.
const MetaKeyTokenSource = "token_source"
MetaKeyTokenSource is the metadata key for recording how a token was obtained. Provider packages define the values (e.g., "cli", "env", "pat").
const OpenAIAPIKeyPlaceholder = "sk-moat-proxy-injected-placeholder-0000000000000000000000000000000000000000"
OpenAIAPIKeyPlaceholder is a placeholder that looks like a valid OpenAI API key. Some tools validate the API key format locally before making requests. Using a valid-looking placeholder bypasses these checks while still allowing the proxy to inject the real key at the network layer.
const ProxyInjectedPlaceholder = "moat-proxy-injected"
ProxyInjectedPlaceholder is a placeholder value for credentials that will be injected by the Moat proxy at runtime. The actual credential never reaches the container; instead, the proxy intercepts requests and adds the real Authorization header. This placeholder signals to tools that a credential is expected without exposing the actual value.
Variables ¶
This section is empty.
Functions ¶
func DefaultEncryptionKey ¶
DefaultEncryptionKey retrieves the encryption key from secure storage. Uses system keychain when available, falls back to file-based storage.
func DefaultStoreDir ¶
func DefaultStoreDir() string
DefaultStoreDir returns the default credential store directory.
func GenerateAccessTokenPlaceholder ¶
GenerateAccessTokenPlaceholder creates a JWT-formatted access token placeholder. The Codex CLI also validates the access_token as a JWT and extracts claims from it. This placeholder mirrors the structure of a real OpenAI access token.
func GenerateIDTokenPlaceholder ¶
GenerateIDTokenPlaceholder creates a JWT-formatted placeholder with the account_id embedded in the claims. This is required for Codex CLI which extracts the chatgpt_account_id from the id_token's JWT claims locally before making API calls.
The generated JWT has: - Header: {"alg":"RS256","typ":"JWT"} - Payload: {"sub":"moat-placeholder","exp":<future>,"https://api.openai.com/auth":{"chatgpt_account_id":"<account_id>"}} - Signature: placeholder (not cryptographically valid)
The signature is not valid, but Codex CLI only decodes the claims - it doesn't verify the signature locally (that's done server-side).
func ImpliedDependencies ¶
ImpliedDependencies returns the dependencies implied by a list of grants. For example, a "github" grant implies "gh" and "git" dependencies.
func IsKnownProvider ¶
IsKnownProvider returns true if the provider is a known credential provider.
func IsOAuthToken ¶
IsOAuthToken returns true if the token appears to be a Claude Code OAuth token.
This uses a prefix-based heuristic: OAuth tokens from Claude Code start with "sk-ant-oat" (Anthropic OAuth Token). This prefix format is based on observed token structure as of 2025. If Anthropic changes their token format in the future, this function may need to be updated.
Note: API keys typically start with "sk-ant-api" for comparison.
func RegisterImpliedDeps ¶
RegisterImpliedDeps registers an implied dependencies function for a provider. This is typically called from init() functions in provider packages.
func RegisterProviderSetup ¶
func RegisterProviderSetup(provider Provider, setup ProviderSetup)
RegisterProviderSetup registers a ProviderSetup for a provider. This is typically called from init() functions in provider packages.
func ValidateGrant ¶
ValidateGrant validates a grant string and returns an error if invalid. Grants must be a known provider, optionally with a scope suffix (e.g., "github:repo").
Types ¶
type AnthropicAuth ¶
type AnthropicAuth struct {
HTTPClient *http.Client // Optional; uses http.DefaultClient if nil
// APIURL allows overriding the endpoint for testing.
APIURL string
}
AnthropicAuth handles Anthropic API key authentication.
func (*AnthropicAuth) CreateCredential ¶
func (a *AnthropicAuth) CreateCredential(apiKey string) Credential
CreateCredential creates a Credential from a validated API key.
func (*AnthropicAuth) PromptForAPIKey ¶
func (a *AnthropicAuth) PromptForAPIKey() (string, error)
PromptForAPIKey prompts the user to enter their Anthropic API key.
func (*AnthropicAuth) ValidateKey ¶
func (a *AnthropicAuth) ValidateKey(ctx context.Context, apiKey string) error
ValidateKey validates an Anthropic API key by making a minimal API request. Returns nil if the key is valid, or an error describing the problem.
type ClaudeCodeCredentials ¶
type ClaudeCodeCredentials struct{}
ClaudeCodeCredentials handles extraction of Claude Code OAuth credentials.
func (*ClaudeCodeCredentials) CreateCredentialFromOAuth ¶
func (c *ClaudeCodeCredentials) CreateCredentialFromOAuth(token *ClaudeOAuthToken) Credential
CreateCredentialFromOAuth creates a Moat Credential from Claude Code OAuth token.
func (*ClaudeCodeCredentials) GetClaudeCodeCredentials ¶
func (c *ClaudeCodeCredentials) GetClaudeCodeCredentials() (*ClaudeOAuthToken, error)
GetClaudeCodeCredentials attempts to retrieve Claude Code OAuth credentials. It tries the following sources in order: 1. macOS Keychain (if on macOS) 2. ~/.claude/.credentials.json file
Returns the credentials if found, or an error describing what went wrong.
func (*ClaudeCodeCredentials) HasClaudeCodeCredentials ¶
func (c *ClaudeCodeCredentials) HasClaudeCodeCredentials() bool
HasClaudeCodeCredentials checks if Claude Code credentials are available.
type ClaudeOAuthCredentials ¶
type ClaudeOAuthCredentials struct {
ClaudeAiOauth *ClaudeOAuthToken `json:"claudeAiOauth,omitempty"`
}
ClaudeOAuthCredentials represents the OAuth credentials stored by Claude Code.
type ClaudeOAuthToken ¶
type ClaudeOAuthToken struct {
AccessToken string `json:"accessToken"`
RefreshToken string `json:"refreshToken"`
ExpiresAt int64 `json:"expiresAt"` // Unix timestamp in milliseconds
Scopes []string `json:"scopes"`
SubscriptionType string `json:"subscriptionType,omitempty"`
RateLimitTier string `json:"rateLimitTier,omitempty"`
}
ClaudeOAuthToken represents an individual OAuth token from Claude Code.
func (*ClaudeOAuthToken) ExpiresAtTime ¶
func (t *ClaudeOAuthToken) ExpiresAtTime() time.Time
ExpiresAtTime returns the expiration time as a time.Time.
func (*ClaudeOAuthToken) IsExpired ¶
func (t *ClaudeOAuthToken) IsExpired() bool
IsExpired returns true if the token has expired.
type Credential ¶
type Credential struct {
Provider Provider `json:"provider"`
Token string `json:"token"`
Scopes []string `json:"scopes,omitempty"`
ExpiresAt time.Time `json:"expires_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
Metadata map[string]string `json:"metadata,omitempty"` // Provider-specific extra data
}
Credential represents a stored credential.
func (*Credential) GetCreatedAt ¶
func (c *Credential) GetCreatedAt() time.Time
GetCreatedAt implements ProviderCredential.
func (*Credential) GetExpiresAt ¶
func (c *Credential) GetExpiresAt() time.Time
GetExpiresAt implements ProviderCredential.
func (*Credential) GetMetadata ¶
func (c *Credential) GetMetadata() map[string]string
GetMetadata implements ProviderCredential.
func (*Credential) GetProvider ¶
func (c *Credential) GetProvider() string
GetProvider implements ProviderCredential.
func (*Credential) GetScopes ¶
func (c *Credential) GetScopes() []string
GetScopes implements ProviderCredential.
func (*Credential) GetToken ¶
func (c *Credential) GetToken() string
GetToken implements ProviderCredential.
type FileStore ¶
type FileStore struct {
// contains filtered or unexported fields
}
FileStore implements Store using encrypted files.
func NewFileStore ¶
NewFileStore creates a file-based credential store. key must be 32 bytes for AES-256.
func (*FileStore) AddSSHMapping ¶
func (s *FileStore) AddSSHMapping(mapping SSHMapping) error
AddSSHMapping adds or updates an SSH host-to-key mapping.
func (*FileStore) Get ¶
func (s *FileStore) Get(provider Provider) (*Credential, error)
Get retrieves a credential for the given provider.
func (*FileStore) GetSSHMappings ¶
func (s *FileStore) GetSSHMappings() ([]SSHMapping, error)
GetSSHMappings returns all SSH host-to-key mappings.
func (*FileStore) GetSSHMappingsForHosts ¶
func (s *FileStore) GetSSHMappingsForHosts(hosts []string) ([]SSHMapping, error)
GetSSHMappingsForHosts returns mappings for the specified hosts.
func (*FileStore) List ¶
func (s *FileStore) List() ([]Credential, error)
List returns all stored credentials.
func (*FileStore) RemoveSSHMapping ¶
RemoveSSHMapping removes an SSH mapping for a host.
func (*FileStore) Save ¶
func (s *FileStore) Save(cred Credential) error
Save stores a credential encrypted on disk.
type OAuthCredentialInfo ¶
OAuthCredentialInfo holds information extracted from an OAuth credential for creating credential files.
type OpenAIAuth ¶
type OpenAIAuth struct {
HTTPClient *http.Client // Optional; uses http.DefaultClient if nil
// APIURL allows overriding the endpoint for testing.
APIURL string
}
OpenAIAuth handles OpenAI API key authentication.
func (*OpenAIAuth) CreateCredential ¶
func (a *OpenAIAuth) CreateCredential(apiKey string) Credential
CreateCredential creates a Credential from a validated API key.
func (*OpenAIAuth) PromptForAPIKey ¶
func (a *OpenAIAuth) PromptForAPIKey() (string, error)
PromptForAPIKey prompts the user to enter their OpenAI API key.
func (*OpenAIAuth) ValidateKey ¶
func (a *OpenAIAuth) ValidateKey(ctx context.Context, apiKey string) error
ValidateKey validates an OpenAI API key by making a minimal API request. Returns nil if the key is valid, or an error describing the problem.
type Provider ¶
type Provider string
Provider identifies a credential provider (github, aws, etc.)
func KnownProviders ¶
func KnownProviders() []Provider
KnownProviders returns a list of all known credential providers.
func ParseGrantProvider ¶
ParseGrantProvider extracts the provider from a grant string. Grants can be "provider" or "provider:scope" format. For example, "github:repo" returns ProviderGitHub.
type ProviderCredential ¶
type ProviderCredential interface {
GetProvider() string
GetToken() string
GetScopes() []string
GetExpiresAt() time.Time
GetCreatedAt() time.Time
GetMetadata() map[string]string
}
ProviderCredential is a minimal interface for provider.Credential conversion. This allows passing credentials to the new provider package without import cycles.
type ProviderResult ¶
type ProviderResult struct {
// Env contains environment variables to add to the container.
Env []string
// Mounts contains mount configurations for the container.
Mounts []container.MountConfig
// CleanupPath is a path to clean up when the run ends (optional).
CleanupPath string
}
ProviderResult holds the result of configuring a provider.
type ProviderSetup ¶
type ProviderSetup interface {
// Provider returns the provider identifier.
Provider() Provider
// ConfigureProxy sets up proxy headers for this credential.
ConfigureProxy(p ProxyConfigurer, cred *Credential)
// ContainerEnv returns environment variables to set in the container.
ContainerEnv(cred *Credential) []string
// ContainerMounts returns mounts needed for this credential.
// The containerHome parameter is the home directory inside the container.
// Returns the mounts and an optional cleanup directory path.
ContainerMounts(cred *Credential, containerHome string) ([]container.MountConfig, string, error)
// Cleanup is called when the run ends to clean up any resources.
// The cleanupPath is the path returned by ContainerMounts.
Cleanup(cleanupPath string)
}
ProviderSetup configures a credential provider for use in a container run. Each provider (GitHub, Anthropic, etc.) implements this interface to handle its specific proxy configuration, environment variables, and container mounts.
func GetProviderSetup ¶
func GetProviderSetup(provider Provider) ProviderSetup
GetProviderSetup returns the ProviderSetup for a given provider. Returns nil if the provider doesn't have a registered setup. Provider packages register their setups via init() using RegisterProviderSetup.
type ProxyConfigurer ¶
type ProxyConfigurer interface {
// SetCredential sets an Authorization header for a host.
SetCredential(host, value string)
// SetCredentialHeader sets a custom header for a host.
SetCredentialHeader(host, headerName, headerValue string)
// SetCredentialWithGrant sets a credential header with grant info for logging.
SetCredentialWithGrant(host, headerName, headerValue, grant string)
// AddExtraHeader adds an additional header to inject for a host.
AddExtraHeader(host, headerName, headerValue string)
// AddResponseTransformer registers a response transformer for a host.
// Transformers are called in registration order after the response is received.
AddResponseTransformer(host string, transformer ResponseTransformer)
// RemoveRequestHeader removes a client-sent header before forwarding.
// Used when injected credentials conflict with client headers.
RemoveRequestHeader(host, headerName string)
// SetTokenSubstitution replaces placeholder tokens with real tokens in both
// Authorization headers and request bodies for a specific host.
// Body substitution is limited to 64KB requests to avoid memory issues.
SetTokenSubstitution(host, placeholder, realToken string)
}
type ResponseTransformer ¶
type ResponseTransformer func(req, resp interface{}) (interface{}, bool)
ProxyConfigurer is the interface for configuring proxy credentials. This avoids importing the proxy package directly. ResponseTransformer modifies HTTP responses for a host. It receives the request and response as interface{} to avoid circular dependencies. Cast to *http.Request and *http.Response in the transformer implementation. Returns the modified response and true if transformed, or original response and false otherwise.
Note on body handling: Transformers are called BEFORE body capture for logging. If you need to inspect the response body, read it within the transformer and return a new response with a fresh body reader. The original body is not rewound after reading.
type SSHMapping ¶
type SSHMapping struct {
Host string `json:"host"`
KeyFingerprint string `json:"key_fingerprint"`
KeyPath string `json:"key_path,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
SSHMapping maps a host to an SSH key fingerprint.
type Store ¶
type Store interface {
Save(cred Credential) error
Get(provider Provider) (*Credential, error)
Delete(provider Provider) error
List() ([]Credential, error)
}
Store defines the credential storage interface.