tessl install tessl/golang-cloud-google-com--go--secretmanager@1.16.1Go 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"