Files
secret/google.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)
}