package secret import ( "encoding/base64" "encoding/hex" "fmt" "strings" "time" ) // Provider for secrets. type Provider interface { // GetSecret loads a secret by named key. GetSecret(key string) (value []byte, err error) } // AmbiguousKey is an error incdicating that the secret doesn't resolve to exactly one item. type AmbiguousKey struct { Key string } func (err AmbiguousKey) Error() string { return fmt.Sprintf("secret: ambigious secret key %q", err.Key) } // NotFound is an error indicating the secret can not be found. type NotFound struct { Key string } func (err NotFound) Error() string { if err.Key == "" { return "secret: not found" } return fmt.Sprintf("secret: %q not found", err.Key) } // ToBinary converts a string to []bytes. // // There are special prefixes for binary encoded formats: // - hex: for hexadecimal encoded strings // - b64: for base-64 encoded strings (raw encoding) // // If a special prefix is found, the appropriate codec will be used to decode to string to []byte, // when there is an error decoding, it may result in an empty value. // // All other strings will be converted to []byte as-is. func ToBinary(s string) (bytes []byte) { switch { case strings.HasPrefix(s, "hex:"): bytes, _ = hex.DecodeString(s[4:]) case strings.HasPrefix(s, "b64:"): bytes, _ = base64.RawStdEncoding.DecodeString(s[4:]) default: bytes = []byte(s) } return } type providerOptions struct { timeout time.Duration apiKey string credentials string clientID string secretID string region string } // Option for providers. type Option func(*providerOptions) func newProviderOptions(opts ...Option) *providerOptions { options := new(providerOptions) for _, opt := range opts { opt(options) } return options } // WithAPIKey sets the provider API key. func WithAPIKey(key string) Option { return func(p *providerOptions) { p.apiKey = key } } // WithCredentials specifies the API credentials. func WithCredentials(credentials string) Option { return func(p *providerOptions) { p.credentials = credentials } } // WithOAuth sets the provider client ID & secret options. func WithOAuth(clientID, secret string) Option { return func(p *providerOptions) { p.clientID = clientID p.secretID = secret } } // WithTimeout sets the provider timeout option. func WithTimeout(timeout time.Duration) Option { return func(p *providerOptions) { p.timeout = timeout } } // WithRegion sets the provider (cloud) region. func WithRegion(region string) Option { return func(p *providerOptions) { p.region = region } }