85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package secret
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
|
|
"google.golang.org/api/option"
|
|
secretmanager "google.golang.org/api/secretmanager/v1"
|
|
)
|
|
|
|
type gcpSecretManagerProvider struct {
|
|
options *providerOptions
|
|
projectID string
|
|
}
|
|
|
|
// GCPSecretManager is a provider for Google Cloud Secret Manager.
|
|
//
|
|
// Authentication must be supplied using `opts`.
|
|
//
|
|
// To use an API key:
|
|
//
|
|
// provider, err := GCPSecretManager(projectID, WithAPIKey("AI..."))
|
|
//
|
|
// To use credentials JSON:
|
|
//
|
|
// provider, err := GCPSecretManager(projectID, WithCredentials("path/to/creds.json"))
|
|
//
|
|
// Alternatively, the following environment variables may be used:
|
|
// - GOOGLE_CLOUD_CREDENTIALS containing a path to the credentials JSON file
|
|
// - GOOGLE_CLOUD_CREDENTIALS_JSON containing the credentials JSON
|
|
func GCPSecretManager(projectID string, opts ...Option) (Provider, error) {
|
|
var options = new(providerOptions)
|
|
for _, opt := range opts {
|
|
opt(options)
|
|
}
|
|
|
|
return &gcpSecretManagerProvider{
|
|
options: options,
|
|
projectID: projectID,
|
|
}, nil
|
|
}
|
|
|
|
func (p *gcpSecretManagerProvider) GetSecret(key string) (value []byte, err error) {
|
|
ctx := context.Background()
|
|
|
|
if p.options.timeout > 0 {
|
|
var cancel func()
|
|
ctx, cancel = context.WithTimeout(ctx, p.options.timeout)
|
|
defer cancel()
|
|
}
|
|
|
|
var opts []option.ClientOption
|
|
if p.options.apiKey != "" {
|
|
opts = append(opts, option.WithAPIKey(p.options.apiKey))
|
|
} else if p.options.credentials != "" {
|
|
opts = append(opts, option.WithCredentialsFile(p.options.credentials))
|
|
} else if v := os.Getenv("GOOGLE_CLOUD_CREDENTIALS"); v != "" {
|
|
opts = append(opts, option.WithCredentialsFile(v))
|
|
} else if v := os.Getenv("GOOGLE_CLOUD_CREDENTIALS_JSON"); v != "" {
|
|
opts = append(opts, option.WithCredentialsJSON([]byte(v)))
|
|
} else {
|
|
// Calling the service without authentication will fail...
|
|
opts = append(opts, option.WithoutAuthentication())
|
|
}
|
|
|
|
var service *secretmanager.Service
|
|
if service, err = secretmanager.NewService(ctx, opts...); err != nil {
|
|
return
|
|
}
|
|
|
|
resource := fmt.Sprintf("projects/%s/secrets/%s/versions/latest",
|
|
url.PathEscape(p.projectID),
|
|
url.PathEscape(key))
|
|
|
|
var response *secretmanager.AccessSecretVersionResponse
|
|
if response, err = service.Projects.Secrets.Versions.Access(resource).Do(); err != nil {
|
|
return
|
|
}
|
|
|
|
return base64.StdEncoding.DecodeString(response.Payload.Data)
|
|
}
|