Go Client Library for Google Cloud Secret Manager API - stores sensitive data such as API keys, passwords, and certificates
—
Secrets are logical containers that hold secret versions. This document covers all operations for managing secrets including creation, retrieval, updating, deletion, and listing.
func (c *Client) CreateSecret(ctx context.Context, req *secretmanagerpb.CreateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error)Creates a new Secret containing no SecretVersions. After creation, add versions using AddSecretVersion.
Request Type:
type CreateSecretRequest struct {
Parent string
SecretId string
Secret *Secret
}Fields:
Parent - Required. The resource name of the project in format projects/* or projects/*/locations/*SecretId - Required. Unique identifier within the project (max 255 chars, alphanumeric, -, _)Secret - Required. A Secret with initial field valuesExample - Create secret with automatic replication:
req := &secretmanagerpb.CreateSecretRequest{
Parent: "projects/my-project",
SecretId: "my-api-key",
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_Automatic_{
Automatic: &secretmanagerpb.Replication_Automatic{},
},
},
},
}
secret, err := client.CreateSecret(ctx, req)
if err != nil {
log.Fatalf("failed to create secret: %v", err)
}
fmt.Printf("Created secret: %s\n", secret.Name)Example - Create secret with user-managed replication:
req := &secretmanagerpb.CreateSecretRequest{
Parent: "projects/my-project",
SecretId: "my-regional-secret",
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_UserManaged_{
UserManaged: &secretmanagerpb.Replication_UserManaged{
Replicas: []*secretmanagerpb.Replication_UserManaged_Replica{
{Location: "us-east1"},
{Location: "us-west1"},
},
},
},
},
Labels: map[string]string{
"environment": "production",
"team": "backend",
},
},
}
secret, err := client.CreateSecret(ctx, req)Example - Create secret with CMEK encryption:
req := &secretmanagerpb.CreateSecretRequest{
Parent: "projects/my-project",
SecretId: "my-encrypted-secret",
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_Automatic_{
Automatic: &secretmanagerpb.Replication_Automatic{
CustomerManagedEncryption: &secretmanagerpb.CustomerManagedEncryption{
KmsKeyName: "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key",
},
},
},
},
},
}
secret, err := client.CreateSecret(ctx, req)func (c *Client) GetSecret(ctx context.Context, req *secretmanagerpb.GetSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error)Gets metadata for a given Secret. This does not include secret data - use AccessSecretVersion to retrieve the actual secret payload.
Request Type:
type GetSecretRequest struct {
Name string
}Fields:
Name - Required. The resource name in format projects/*/secrets/* or projects/*/locations/*/secrets/*Example:
req := &secretmanagerpb.GetSecretRequest{
Name: "projects/my-project/secrets/my-api-key",
}
secret, err := client.GetSecret(ctx, req)
if err != nil {
log.Fatalf("failed to get secret: %v", err)
}
fmt.Printf("Secret: %s\n", secret.Name)
fmt.Printf("Created: %s\n", secret.CreateTime.AsTime())
fmt.Printf("Labels: %v\n", secret.Labels)func (c *Client) UpdateSecret(ctx context.Context, req *secretmanagerpb.UpdateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error)Updates metadata of an existing Secret. The secret data itself cannot be updated - create a new version instead.
Request Type:
type UpdateSecretRequest struct {
Secret *Secret
UpdateMask *fieldmaskpb.FieldMask
}Fields:
Secret - Required. Secret with updated field valuesUpdateMask - Required. Specifies the fields to be updatedExample - Update labels:
import "google.golang.org/protobuf/types/known/fieldmaskpb"
secret := &secretmanagerpb.Secret{
Name: "projects/my-project/secrets/my-api-key",
Labels: map[string]string{
"environment": "staging",
"updated": "true",
},
}
req := &secretmanagerpb.UpdateSecretRequest{
Secret: secret,
UpdateMask: &fieldmaskpb.FieldMask{
Paths: []string{"labels"},
},
}
updatedSecret, err := client.UpdateSecret(ctx, req)
if err != nil {
log.Fatalf("failed to update secret: %v", err)
}Example - Add rotation policy:
import (
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"
)
nextRotation := time.Now().Add(30 * 24 * time.Hour) // 30 days from now
secret := &secretmanagerpb.Secret{
Name: "projects/my-project/secrets/my-api-key",
Rotation: &secretmanagerpb.Rotation{
NextRotationTime: timestamppb.New(nextRotation),
RotationPeriod: durationpb.New(30 * 24 * time.Hour),
},
}
req := &secretmanagerpb.UpdateSecretRequest{
Secret: secret,
UpdateMask: &fieldmaskpb.FieldMask{
Paths: []string{"rotation"},
},
}
updatedSecret, err := client.UpdateSecret(ctx, req)Example - Set expiration time:
expireTime := time.Now().Add(365 * 24 * time.Hour) // 1 year from now
secret := &secretmanagerpb.Secret{
Name: "projects/my-project/secrets/my-api-key",
Expiration: &secretmanagerpb.Secret_ExpireTime{
ExpireTime: timestamppb.New(expireTime),
},
}
req := &secretmanagerpb.UpdateSecretRequest{
Secret: secret,
UpdateMask: &fieldmaskpb.FieldMask{
Paths: []string{"expire_time"},
},
}
updatedSecret, err := client.UpdateSecret(ctx, req)func (c *Client) DeleteSecret(ctx context.Context, req *secretmanagerpb.DeleteSecretRequest, opts ...gax.CallOption) errorDeletes a Secret. This permanently deletes the secret and all of its versions.
Request Type:
type DeleteSecretRequest struct {
Name string
Etag string
}Fields:
Name - Required. The resource name in format projects/*/secrets/*Etag - Optional. Etag of the Secret for optimistic concurrency controlExample:
req := &secretmanagerpb.DeleteSecretRequest{
Name: "projects/my-project/secrets/my-api-key",
}
err := client.DeleteSecret(ctx, req)
if err != nil {
log.Fatalf("failed to delete secret: %v", err)
}
fmt.Println("Secret deleted successfully")Example with etag for concurrency control:
// First, get the secret to obtain its etag
getReq := &secretmanagerpb.GetSecretRequest{
Name: "projects/my-project/secrets/my-api-key",
}
secret, err := client.GetSecret(ctx, getReq)
if err != nil {
log.Fatalf("failed to get secret: %v", err)
}
// Delete using the etag
deleteReq := &secretmanagerpb.DeleteSecretRequest{
Name: secret.Name,
Etag: secret.Etag,
}
err = client.DeleteSecret(ctx, deleteReq)
if err != nil {
// If the etag doesn't match, the secret was modified and delete will fail
log.Fatalf("failed to delete secret: %v", err)
}func (c *Client) ListSecrets(ctx context.Context, req *secretmanagerpb.ListSecretsRequest, opts ...gax.CallOption) *SecretIteratorLists Secrets in a project.
Request Type:
type ListSecretsRequest struct {
Parent string
PageSize int32
PageToken string
Filter string
}Fields:
Parent - Required. The resource name in format projects/* or projects/*/locations/*PageSize - Optional. Maximum number of results per page (max 25000)PageToken - Optional. Token from a previous request to retrieve the next pageFilter - Optional. Filter string for matching secretsIterator Type:
type SecretIterator struct {
Response interface{}
InternalFetch func(pageSize int, pageToken string) (results []*secretmanagerpb.Secret, nextPageToken string, err error)
}Iterator Methods:
func (it *SecretIterator) Next() (*secretmanagerpb.Secret, error)
func (it *SecretIterator) PageInfo() *iterator.PageInfo
func (it *SecretIterator) All() iter.Seq2[*secretmanagerpb.Secret, error]Example - List all secrets:
req := &secretmanagerpb.ListSecretsRequest{
Parent: "projects/my-project",
}
it := client.ListSecrets(ctx, req)
for {
secret, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("failed to list secrets: %v", err)
}
fmt.Printf("Secret: %s\n", secret.Name)
}Example - List with pagination:
req := &secretmanagerpb.ListSecretsRequest{
Parent: "projects/my-project",
PageSize: 10,
}
it := client.ListSecrets(ctx, req)
pageInfo := it.PageInfo()
for {
secret, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("Secret: %s\n", secret.Name)
}Example - List with filter:
// Filter by label
req := &secretmanagerpb.ListSecretsRequest{
Parent: "projects/my-project",
Filter: "labels.environment=production",
}
it := client.ListSecrets(ctx, req)
for {
secret, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("Production secret: %s\n", secret.Name)
}Example - Using Go 1.23+ iterator:
req := &secretmanagerpb.ListSecretsRequest{
Parent: "projects/my-project",
}
it := client.ListSecrets(ctx, req)
for secret, err := range it.All() {
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("Secret: %s\n", secret.Name)
}type ListSecretsResponse struct {
Secrets []*Secret
NextPageToken string
TotalSize int32
}Fields:
Secrets - The list of Secrets sorted in reverse by create_timeNextPageToken - Token to retrieve the next pageTotalSize - Total number of Secrets (0 when filter is set)This type is used internally by the iterator and is not typically used directly.
Labels are key-value pairs for organizing secrets:
Secret: &secretmanagerpb.Secret{
Labels: map[string]string{
"environment": "production",
"application": "web-server",
"tier": "backend",
},
}Limitations:
Annotations provide custom metadata (not used for filtering):
Secret: &secretmanagerpb.Secret{
Annotations: map[string]string{
"description": "API key for external service",
"owner": "team@example.com",
"created_by": "automation-system",
},
}Limitations:
Map custom aliases to version numbers:
Secret: &secretmanagerpb.Secret{
VersionAliases: map[string]int64{
"stable": 5,
"canary": 6,
"latest": 6,
},
}Limitations:
Secrets can expire automatically:
Expire at specific time:
Secret: &secretmanagerpb.Secret{
Expiration: &secretmanagerpb.Secret_ExpireTime{
ExpireTime: timestamppb.New(time.Now().Add(365 * 24 * time.Hour)),
},
}Expire after TTL:
Secret: &secretmanagerpb.Secret{
Expiration: &secretmanagerpb.Secret_Ttl{
Ttl: durationpb.New(365 * 24 * time.Hour),
},
}Configure Pub/Sub topics for notifications about secret operations:
Secret: &secretmanagerpb.Secret{
Topics: []*secretmanagerpb.Topic{
{Name: "projects/my-project/topics/secret-notifications"},
},
}Limitations:
The Filter parameter supports various query patterns:
// Filter by label
Filter: "labels.environment=production"
// Filter by multiple labels
Filter: "labels.environment=production AND labels.tier=backend"
// Filter by name (partial match)
Filter: "name:api-key"Install with Tessl CLI
npx tessl i tessl/golang-cloud-google-com--go--secretmanager