GCP

Google Cloud Secret Manager, built on cloud.google.com/go/secretmanager.

Schemegcp-sm://
Modulegithub.com/xavidop/mamori/providers/gcp
Sensitiveyes
Watchpoll
AuthApplication 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>]
PartRequiredWhat it means
<project>yesThe GCP project ID (or number).
<secret>yesThe secret ID within that project.
#json-keynoSelect one field from a JSON secret payload (via mamori.SelectKey).
?version=<v>noPin a specific secret version. Defaults to latest.

Examples

  • gcp-sm://my-project/db-password reads the latest version of db-password.
  • gcp-sm://my-project/api-key?version=3 pins version 3, so the value never changes under you.
  • gcp-sm://my-project/creds#password selects the password field 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 codemamori kind
NotFoundnot_found
PermissionDeniedpermission_denied
Unauthenticatedunauthenticated
Unavailable, DeadlineExceededunavailable
ResourceExhaustedrate_limited
InvalidArgumentinvalid
anything elseunknown

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.