From 65cbf971394c19e223139fe7145e99cd5711882f Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 12:32:32 +0100 Subject: [PATCH 01/15] Add CredentialSource interface and include credential source in errors This interface is meant to be implemented by credential readers and add more information to credential-related errors. If implemented by a credential reader, every credential parsing, decoding and decrypting error will also include the source of the credential (path to credential file or environment variable name). --- pkg/secrethub/configdir/dir.go | 5 +++++ pkg/secrethub/credentials/key.go | 10 +++++++++ pkg/secrethub/credentials/providers.go | 13 ++++++++++- pkg/secrethub/credentials/readers.go | 30 +++++++++++++++++++++----- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/pkg/secrethub/configdir/dir.go b/pkg/secrethub/configdir/dir.go index 51b6106b..c8f83218 100644 --- a/pkg/secrethub/configdir/dir.go +++ b/pkg/secrethub/configdir/dir.go @@ -77,6 +77,11 @@ func (f *CredentialFile) Path() string { return f.path } +// Source returns the path to the credential file. +func (f *CredentialFile) Source() string { + return f.path +} + // Write writes the given bytes to the credential file. func (f *CredentialFile) Write(data []byte) error { err := os.MkdirAll(filepath.Dir(f.path), os.FileMode(0700)) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index 211c2767..53cc835e 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -2,12 +2,22 @@ package credentials import ( "errors" + "fmt" "github.com/secrethub/secrethub-go/internals/auth" "github.com/secrethub/secrethub-go/internals/crypto" "github.com/secrethub/secrethub-go/pkg/secrethub/internals/http" ) +type ErrLoadingCredential struct { + Location string + Err error +} + +func (e ErrLoadingCredential) Error() string { + return fmt.Sprintf("error loading credential loaded from '%s': %v", e.Location, e.Err) +} + // Key is a credential that uses a local key for all its operations. type Key struct { key *RSACredential diff --git a/pkg/secrethub/credentials/providers.go b/pkg/secrethub/credentials/providers.go index 858160c2..14be6918 100644 --- a/pkg/secrethub/credentials/providers.go +++ b/pkg/secrethub/credentials/providers.go @@ -39,7 +39,12 @@ func (k KeyProvider) Passphrase(passphraseReader Reader) Provider { // Provide implements the Provider interface for a KeyProvider. func (k KeyProvider) Provide(httpClient *http.Client) (auth.Authenticator, Decrypter, error) { key, err := ImportKey(k.credentialReader, k.passphraseReader) - if err != nil { + if source, ok := k.credentialReader.(CredentialSource); ok && err != nil { + return nil, nil, ErrLoadingCredential{ + Location: source.Source(), + Err: err, + } + } else if err != nil { return nil, nil, err } return key.Provide(httpClient) @@ -52,3 +57,9 @@ type providerFunc func(*http.Client) (auth.Authenticator, Decrypter, error) func (f providerFunc) Provide(httpClient *http.Client) (auth.Authenticator, Decrypter, error) { return f(httpClient) } + +// CredentialSource should be implemented by credential readers to allow returning credential reading errors +// that include the credentials source (e.g. path to credential file, environment variable etc.). +type CredentialSource interface { + Source() string +} diff --git a/pkg/secrethub/credentials/readers.go b/pkg/secrethub/credentials/readers.go index 67fe88bd..9d1fdaab 100644 --- a/pkg/secrethub/credentials/readers.go +++ b/pkg/secrethub/credentials/readers.go @@ -14,7 +14,7 @@ type Reader interface { // FromFile returns a reader that reads the contents of a file, // e.g. a credential or a passphrase. func FromFile(path string) Reader { - return readerFunc(func() ([]byte, error) { + return newReader(path, func() ([]byte, error) { return ioutil.ReadFile(path) }) } @@ -22,7 +22,7 @@ func FromFile(path string) Reader { // FromEnv returns a reader that reads the contents of an // environment variable, e.g. a credential or a passphrase. func FromEnv(key string) Reader { - return readerFunc(func() ([]byte, error) { + return newReader("$"+key, func() ([]byte, error) { return []byte(os.Getenv(key)), nil }) } @@ -43,10 +43,30 @@ func FromString(raw string) Reader { }) } -// readerFunc is a helper function to create a reader from any func() ([]byte, error). type readerFunc func() ([]byte, error) +func (r readerFunc) Read() ([]byte, error) { + return r() +} + +// newReader is a helper function to create a reader with a source from any func() ([]byte, error). +func newReader(source string, read func() ([]byte, error)) Reader { + return reader{ + source: source, + readFunc: read, + } +} + +type reader struct { + source string + readFunc func() ([]byte, error) +} + +func (r reader) Source() string { + return r.source +} + // Read implements the Reader interface. -func (f readerFunc) Read() ([]byte, error) { - return f() +func (r reader) Read() ([]byte, error) { + return r.readFunc() } From 27c7b3dec4b0ace5b76b3dd46c2c4558a25274e7 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 12:40:24 +0100 Subject: [PATCH 02/15] Use credential.FromEnv for reading environment variable --- pkg/secrethub/client.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/secrethub/client.go b/pkg/secrethub/client.go index 5e0802b7..cc492b44 100644 --- a/pkg/secrethub/client.go +++ b/pkg/secrethub/client.go @@ -264,9 +264,10 @@ func (c *Client) with(options ...ClientOption) error { // sourcing it either from the SECRETHUB_CREDENTIAL environment variable or // from the configuration directory. func (c *Client) DefaultCredential() credentials.Reader { - envCredential := os.Getenv("SECRETHUB_CREDENTIAL") + const credentialEnvironmentVariable = "SECRETHUB_CREDENTIAL" + envCredential := os.Getenv(credentialEnvironmentVariable) if envCredential != "" { - return credentials.FromString(envCredential) + return credentials.FromEnv(credentialEnvironmentVariable) } return c.ConfigDir.Credential() From 2bcd52959a2a611c37ee20d8ec4aa32fb06daa6d Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 12:41:21 +0100 Subject: [PATCH 03/15] Prevent credentials.FromEnv from delaying env var read --- pkg/secrethub/credentials/readers.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/readers.go b/pkg/secrethub/credentials/readers.go index 9d1fdaab..0efcfd2a 100644 --- a/pkg/secrethub/credentials/readers.go +++ b/pkg/secrethub/credentials/readers.go @@ -22,8 +22,9 @@ func FromFile(path string) Reader { // FromEnv returns a reader that reads the contents of an // environment variable, e.g. a credential or a passphrase. func FromEnv(key string) Reader { + credential := os.Getenv(key) return newReader("$"+key, func() ([]byte, error) { - return []byte(os.Getenv(key)), nil + return []byte(credential), nil }) } From bbe89cb9951a032d6f401ae56509872b68924c17 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 12:43:36 +0100 Subject: [PATCH 04/15] Add more detailed no passphrase error --- pkg/secrethub/credentials/encoding.go | 1 + pkg/secrethub/credentials/key.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/encoding.go b/pkg/secrethub/credentials/encoding.go index 3ed72ddf..72bf6b94 100644 --- a/pkg/secrethub/credentials/encoding.go +++ b/pkg/secrethub/credentials/encoding.go @@ -25,6 +25,7 @@ var ( ErrCannotDecodeCredentialPayload = errCredentials.Code("invalid_credential_header").ErrorPref("cannot decode credential payload: %v") ErrCannotDecodeEncryptedCredential = errCredentials.Code("cannot_decode_encrypted_credential").Error("cannot decode an encrypted credential without a key") ErrCannotDecryptCredential = errCredentials.Code("cannot_decrypt_credential").Error("passphrase is incorrect") + ErrNeedPassphrase = errCredentials.Code("credential_passphrase_required").Error("default credential is password-protected. Configure the client to use service credential by provisioning one through the SECRETHUB_CREDENTIAL environment variable") ErrMalformedCredential = errCredentials.Code("malformed_credential").ErrorPref("credential is malformed: %v") ErrInvalidKey = errCredentials.Code("invalid_key").Error("the given key is not valid for the encryption algorithm") ) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index 53cc835e..8c3b535b 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -80,7 +80,7 @@ func ImportKey(credentialReader, passphraseReader Reader) (Key, error) { } if encoded.IsEncrypted() { if passphraseReader == nil { - return Key{}, errors.New("need passphrase") + return Key{}, ErrNeedPassphrase } // Try up to three times to get the correct passphrase. From 4de867f48fe19067ebce297228351b3c5dbdaa5a Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 12:54:36 +0100 Subject: [PATCH 05/15] Check SECRETHUB_CREDENTIAL_PASSPHRASE envvar if no passphrase reader is given --- pkg/secrethub/credentials/key.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index 8c3b535b..90e086ed 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -3,6 +3,7 @@ package credentials import ( "errors" "fmt" + "os" "github.com/secrethub/secrethub-go/internals/auth" "github.com/secrethub/secrethub-go/internals/crypto" @@ -79,9 +80,17 @@ func ImportKey(credentialReader, passphraseReader Reader) (Key, error) { return Key{}, err } if encoded.IsEncrypted() { - if passphraseReader == nil { + envPassphrase := os.Getenv("SECRETHUB_CREDENTIAL_PASSPHRASE") + if passphraseReader == nil && envPassphrase == "" { return Key{}, ErrNeedPassphrase } + if passphraseReader == nil { + credential, err := decryptKey([]byte(envPassphrase), encoded) + if err != nil { + return Key{}, err + } + return Key{key:credential}, nil + } // Try up to three times to get the correct passphrase. for i := 0; i < 3; i++ { From 6c73171158acf618df90ae6d9423193fb1e56e8f Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 12:55:40 +0100 Subject: [PATCH 06/15] Run goimports --- pkg/secrethub/credentials/key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index 90e086ed..a1aa6a9f 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -89,7 +89,7 @@ func ImportKey(credentialReader, passphraseReader Reader) (Key, error) { if err != nil { return Key{}, err } - return Key{key:credential}, nil + return Key{key: credential}, nil } // Try up to three times to get the correct passphrase. From 12e9d3df0aa5de0a3aaf0f4281df5f44fb2d4c54 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 11 Nov 2020 13:04:35 +0100 Subject: [PATCH 07/15] Make SECRETHUB_CREDENTIAL_PASSPHRASE have priority over passphrase reader --- pkg/secrethub/credentials/key.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index a1aa6a9f..cd1045ed 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -81,16 +81,16 @@ func ImportKey(credentialReader, passphraseReader Reader) (Key, error) { } if encoded.IsEncrypted() { envPassphrase := os.Getenv("SECRETHUB_CREDENTIAL_PASSPHRASE") - if passphraseReader == nil && envPassphrase == "" { - return Key{}, ErrNeedPassphrase - } - if passphraseReader == nil { + if envPassphrase != "" { credential, err := decryptKey([]byte(envPassphrase), encoded) if err != nil { return Key{}, err } return Key{key: credential}, nil } + if passphraseReader == nil { + return Key{}, ErrNeedPassphrase + } // Try up to three times to get the correct passphrase. for i := 0; i < 3; i++ { From a86d7da02e9f7e13813a482f20570c9850d2fa49 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 2 Dec 2020 16:04:46 +0200 Subject: [PATCH 08/15] Update pkg/secrethub/credentials/key.go Co-authored-by: Simon Barendse --- pkg/secrethub/credentials/key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index cd1045ed..0c2f89e2 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -16,7 +16,7 @@ type ErrLoadingCredential struct { } func (e ErrLoadingCredential) Error() string { - return fmt.Sprintf("error loading credential loaded from '%s': %v", e.Location, e.Err) + return "load credential " + e.Location + ": " + e.Err.Error() } // Key is a credential that uses a local key for all its operations. From 57d464b59bf9b62f681c3e05b84d7671b7c5f642 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 2 Dec 2020 16:08:35 +0200 Subject: [PATCH 09/15] Refactor err check Co-authored-by: Simon Barendse --- pkg/secrethub/credentials/providers.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/secrethub/credentials/providers.go b/pkg/secrethub/credentials/providers.go index 14be6918..c68d4dfd 100644 --- a/pkg/secrethub/credentials/providers.go +++ b/pkg/secrethub/credentials/providers.go @@ -39,12 +39,13 @@ func (k KeyProvider) Passphrase(passphraseReader Reader) Provider { // Provide implements the Provider interface for a KeyProvider. func (k KeyProvider) Provide(httpClient *http.Client) (auth.Authenticator, Decrypter, error) { key, err := ImportKey(k.credentialReader, k.passphraseReader) - if source, ok := k.credentialReader.(CredentialSource); ok && err != nil { - return nil, nil, ErrLoadingCredential{ - Location: source.Source(), - Err: err, + if err != nil { + if source, ok := k.credentialReader.(CredentialSource); ok { + return nil, nil, ErrLoadingCredential{ + Location: source.Source(), + Err: err, + } } - } else if err != nil { return nil, nil, err } return key.Provide(httpClient) From 53bddabda5712d03c8f55083515f39c83c57851d Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 2 Dec 2020 15:15:19 +0100 Subject: [PATCH 10/15] Remove unused import --- pkg/secrethub/credentials/key.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index 0c2f89e2..b90ac157 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -2,7 +2,6 @@ package credentials import ( "errors" - "fmt" "os" "github.com/secrethub/secrethub-go/internals/auth" From 48e536f6c714df3841c286ba7765c4a49f6ffffc Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Wed, 2 Dec 2020 16:18:49 +0200 Subject: [PATCH 11/15] Improve 'Need Passphrase' error Co-authored-by: Simon Barendse --- pkg/secrethub/credentials/encoding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/encoding.go b/pkg/secrethub/credentials/encoding.go index 72bf6b94..1151bf33 100644 --- a/pkg/secrethub/credentials/encoding.go +++ b/pkg/secrethub/credentials/encoding.go @@ -25,7 +25,7 @@ var ( ErrCannotDecodeCredentialPayload = errCredentials.Code("invalid_credential_header").ErrorPref("cannot decode credential payload: %v") ErrCannotDecodeEncryptedCredential = errCredentials.Code("cannot_decode_encrypted_credential").Error("cannot decode an encrypted credential without a key") ErrCannotDecryptCredential = errCredentials.Code("cannot_decrypt_credential").Error("passphrase is incorrect") - ErrNeedPassphrase = errCredentials.Code("credential_passphrase_required").Error("default credential is password-protected. Configure the client to use service credential by provisioning one through the SECRETHUB_CREDENTIAL environment variable") + ErrNeedPassphrase = errCredentials.Code("credential_passphrase_required").Error("credential is password-protected. Configure the client to use service credential by provisioning one through the SECRETHUB_CREDENTIAL environment variable") ErrMalformedCredential = errCredentials.Code("malformed_credential").ErrorPref("credential is malformed: %v") ErrInvalidKey = errCredentials.Code("invalid_key").Error("the given key is not valid for the encryption algorithm") ) From fd75ad861eef600af471f696769786cefffff0a9 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 4 Dec 2020 16:57:29 +0100 Subject: [PATCH 12/15] Add option set set a default passphrase that is used for the default key credential This allows setting a passphrase without having to provide a credential itself, which can be used to make configuring the Terraform provider easier. --- pkg/secrethub/client.go | 11 +++++++---- pkg/secrethub/client_options.go | 9 +++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pkg/secrethub/client.go b/pkg/secrethub/client.go index cc492b44..1c73c11d 100644 --- a/pkg/secrethub/client.go +++ b/pkg/secrethub/client.go @@ -82,6 +82,8 @@ type Client struct { // These are cached repoIndexKeys map[api.RepoPath]*crypto.SymmetricKey + defaultPassphraseReader credentials.Reader + appInfo []*AppInfo ConfigDir *configdir.Dir } @@ -119,9 +121,10 @@ func (i AppInfo) ValidateName() error { // If no key credential could be found, a Client is returned that can only be used for unauthenticated routes. func NewClient(with ...ClientOption) (*Client, error) { client := &Client{ - httpClient: http.NewClient(), - repoIndexKeys: make(map[api.RepoPath]*crypto.SymmetricKey), - appInfo: []*AppInfo{}, + httpClient: http.NewClient(), + repoIndexKeys: make(map[api.RepoPath]*crypto.SymmetricKey), + appInfo: []*AppInfo{}, + defaultPassphraseReader: credentials.FromEnv("SECRETHUB_CREDENTIAL_PASSPHRASE"), } err := client.with(with...) if err != nil { @@ -144,7 +147,7 @@ func NewClient(with ...ClientOption) (*Client, error) { var provider credentials.Provider switch strings.ToLower(identityProvider) { case "", "key": - provider = credentials.UseKey(client.DefaultCredential()) + provider = credentials.UseKey(client.DefaultCredential()).Passphrase(client.defaultPassphraseReader) case "aws": provider = credentials.UseAWS() case "gcp": diff --git a/pkg/secrethub/client_options.go b/pkg/secrethub/client_options.go index 7ad43796..2c867b8e 100644 --- a/pkg/secrethub/client_options.go +++ b/pkg/secrethub/client_options.go @@ -78,3 +78,12 @@ func WithCredentials(provider credentials.Provider) ClientOption { return nil } } + +// WithDefaultPassphraseReader sets a default passphrase reader that is used for decrypting an encrypted key credential +// if no credential is set explicitly. +func WithDefaultPassphraseReader(reader credentials.Reader) ClientOption { + return func(c *Client) error { + c.defaultPassphraseReader = reader + return nil + } +} From d81fe5a62239e24c4e1e05266cf670ee580854bd Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 15 Dec 2020 15:59:15 +0100 Subject: [PATCH 13/15] Delay reading of credential from environment variable --- pkg/secrethub/credentials/readers.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/secrethub/credentials/readers.go b/pkg/secrethub/credentials/readers.go index 0efcfd2a..9d1fdaab 100644 --- a/pkg/secrethub/credentials/readers.go +++ b/pkg/secrethub/credentials/readers.go @@ -22,9 +22,8 @@ func FromFile(path string) Reader { // FromEnv returns a reader that reads the contents of an // environment variable, e.g. a credential or a passphrase. func FromEnv(key string) Reader { - credential := os.Getenv(key) return newReader("$"+key, func() ([]byte, error) { - return []byte(credential), nil + return []byte(os.Getenv(key)), nil }) } From e5f45b9d8a0dd7bc2c10b0a77a50556d7d2b1d87 Mon Sep 17 00:00:00 2001 From: Marton Soos Date: Tue, 15 Dec 2020 16:06:59 +0100 Subject: [PATCH 14/15] Wrap errors regarding credential passphrase and specify passphrase source --- pkg/secrethub/credentials/key.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/secrethub/credentials/key.go b/pkg/secrethub/credentials/key.go index b90ac157..23e039d9 100644 --- a/pkg/secrethub/credentials/key.go +++ b/pkg/secrethub/credentials/key.go @@ -2,6 +2,7 @@ package credentials import ( "errors" + "fmt" "os" "github.com/secrethub/secrethub-go/internals/auth" @@ -79,11 +80,12 @@ func ImportKey(credentialReader, passphraseReader Reader) (Key, error) { return Key{}, err } if encoded.IsEncrypted() { - envPassphrase := os.Getenv("SECRETHUB_CREDENTIAL_PASSPHRASE") + const credentialPassphraseEnvVar = "SECRETHUB_CREDENTIAL_PASSPHRASE" + envPassphrase := os.Getenv(credentialPassphraseEnvVar) if envPassphrase != "" { credential, err := decryptKey([]byte(envPassphrase), encoded) if err != nil { - return Key{}, err + return Key{}, fmt.Errorf("decrypting credential with passphrase read from $%s: %v", credentialPassphraseEnvVar, err) } return Key{key: credential}, nil } From 38d7f3b3fecf3d3f6a594dddba1f5c249f8e97fa Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Tue, 15 Dec 2020 17:08:36 +0100 Subject: [PATCH 15/15] fix need passphrase error message Co-authored-by: Marton Soos --- pkg/secrethub/credentials/encoding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/secrethub/credentials/encoding.go b/pkg/secrethub/credentials/encoding.go index 1151bf33..0c22d047 100644 --- a/pkg/secrethub/credentials/encoding.go +++ b/pkg/secrethub/credentials/encoding.go @@ -25,7 +25,7 @@ var ( ErrCannotDecodeCredentialPayload = errCredentials.Code("invalid_credential_header").ErrorPref("cannot decode credential payload: %v") ErrCannotDecodeEncryptedCredential = errCredentials.Code("cannot_decode_encrypted_credential").Error("cannot decode an encrypted credential without a key") ErrCannotDecryptCredential = errCredentials.Code("cannot_decrypt_credential").Error("passphrase is incorrect") - ErrNeedPassphrase = errCredentials.Code("credential_passphrase_required").Error("credential is password-protected. Configure the client to use service credential by provisioning one through the SECRETHUB_CREDENTIAL environment variable") + ErrNeedPassphrase = errCredentials.Code("credential_passphrase_required").Error("credential is password-protected. Configure a credential passphrase through the SECRETHUB_CREDENTIAL_PASSPHRASE environment variable or use a credential that is not password-protected") ErrMalformedCredential = errCredentials.Code("malformed_credential").ErrorPref("credential is malformed: %v") ErrInvalidKey = errCredentials.Code("invalid_key").Error("the given key is not valid for the encryption algorithm") )