GCP
Google Cloud Secret Manager, built on cloud.google.com/go/secretmanager.
| Scheme | gcp-sm:// |
| Module | github.com/xavidop/mamori/providers/gcp |
| Sensitive | yes |
| Watch | poll |
| Auth | Application Default Credentials |
Install
go get github.com/xavidop/mamori/providers/gcp
import _ "github.com/xavidop/mamori/providers/gcp"
Using the ref
A gcp-sm:// ref points at one secret in a GCP project’s Secret Manager, at a specific (or the latest) version.
gcp-sm://<project>/<secret>[#json-key][?version=<v>]
| Part | Required | What it means |
|---|---|---|
<project> | yes | The GCP project ID (or number). |
<secret> | yes | The secret ID within that project. |
#json-key | no | Select one field from a JSON secret payload (via mamori.SelectKey). |
?version=<v> | no | Pin a specific secret version. Defaults to latest. |
Examples
gcp-sm://my-project/db-passwordreads the latest version ofdb-password.gcp-sm://my-project/api-key?version=3pins version3, so the value never changes under you.gcp-sm://my-project/creds#passwordselects thepasswordfield of a JSON secret.
type Config struct {
DBPassword secret.String `source:"gcp-sm://my-project/db-password"` // latest version
APIKey secret.String `source:"gcp-sm://my-project/api-key?version=3"` // pinned version
Nested secret.String `source:"gcp-sm://my-project/creds#password"` // key of a JSON secret
}
Values are always Sensitive, and Value.Version is the resolved secret version name (e.g. .../versions/3), so change detection is cheap.
Explicit configuration
Authentication uses Application Default Credentials (a service-account key file via GOOGLE_APPLICATION_CREDENTIALS, workload identity, or the metadata server). For tests or custom transports, inject a client:
import gcpprov "github.com/xavidop/mamori/providers/gcp"
mamori.WithProvider(gcpprov.New(gcpprov.WithClient(myClient)))
Close() is idempotent and terminal: after it returns, every Resolve reports errors.Is(err, mamori.ErrUnavailable) locally, without contacting Secret Manager. It releases the backing client, but only one this provider built itself: the default client, or one produced by WithClientFactory, which is built on the provider’s behalf and released by Close the same as the default. A client injected directly with WithClient belongs to the caller and is left open; closing it would reach outside this provider and break whatever else the caller is using it for.
Watch
Secret Manager has no native change notification, so mamori polls (WithPollInterval + jitter). Pub/Sub rotation notifications can drive an on-demand Load in your app if you need push.
Error classification
| gRPC code | mamori kind |
|---|---|
NotFound | not_found |
PermissionDenied | permission_denied |
Unauthenticated | unauthenticated |
Unavailable, DeadlineExceeded | unavailable |
ResourceExhausted | rate_limited |
InvalidArgument | invalid |
| anything else | unknown |
A malformed ref (not <project>/<secret>) reports invalid without a round trip to Secret Manager. The gRPC status stays reachable through status.Code.
Verified by unit tests and the conformance kit against an in-memory fake; live GCP behavior is covered by //go:build integration tests.