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
Secret versions contain the actual secret data. Each version is immutable once created and has a lifecycle state (enabled, disabled, or destroyed). This document covers all operations for managing secret versions.
func (c *Client) AddSecretVersion(ctx context.Context, req *secretmanagerpb.AddSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)Creates a new SecretVersion containing secret data and attaches it to an existing Secret.
Request Type:
type AddSecretVersionRequest struct {
Parent string
Payload *SecretPayload
}Fields:
Parent - Required. The resource name of the Secret in format projects/*/secrets/* or projects/*/locations/*/secrets/*Payload - Required. The secret payload of the SecretVersionExample - Add secret version:
req := &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/my-project/secrets/my-api-key",
Payload: &secretmanagerpb.SecretPayload{
Data: []byte("my-secret-value"),
},
}
version, err := client.AddSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to add secret version: %v", err)
}
fmt.Printf("Added version: %s\n", version.Name)
fmt.Printf("State: %v\n", version.State)Example - Add version with CRC32C checksum:
import "hash/crc32"
data := []byte("my-secret-value")
crc32c := int64(crc32.Checksum(data, crc32.MakeTable(crc32.Castagnoli)))
req := &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/my-project/secrets/my-api-key",
Payload: &secretmanagerpb.SecretPayload{
Data: data,
DataCrc32C: &crc32c,
},
}
version, err := client.AddSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to add secret version: %v", err)
}
// Check if checksum was validated
if version.ClientSpecifiedPayloadChecksum {
fmt.Println("Checksum was validated by server")
}Example - Add version from file:
import "os"
data, err := os.ReadFile("/path/to/secret.txt")
if err != nil {
log.Fatalf("failed to read file: %v", err)
}
req := &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/my-project/secrets/my-api-key",
Payload: &secretmanagerpb.SecretPayload{
Data: data,
},
}
version, err := client.AddSecretVersion(ctx, req)func (c *Client) AccessSecretVersion(ctx context.Context, req *secretmanagerpb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error)Accesses a SecretVersion. This call returns the secret data. Projects must have enabled the Secret Manager API to use this method.
Request Type:
type AccessSecretVersionRequest struct {
Name string
}Fields:
Name - Required. The resource name of the SecretVersion in format projects/*/secrets/*/versions/* or projects/*/locations/*/secrets/*/versions/*Response Type:
type AccessSecretVersionResponse struct {
Name string
Payload *SecretPayload
}Fields:
Name - The resource name of the SecretVersionPayload - Secret payload containing the dataExample - Access specific version:
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/1",
}
resp, err := client.AccessSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to access secret version: %v", err)
}
fmt.Printf("Secret data: %s\n", resp.Payload.Data)Example - Access latest version:
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/latest",
}
resp, err := client.AccessSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to access secret version: %v", err)
}
secretValue := string(resp.Payload.Data)
fmt.Printf("Latest secret value: %s\n", secretValue)Example - Access version by alias:
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/stable",
}
resp, err := client.AccessSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to access secret version: %v", err)
}
fmt.Printf("Stable version data: %s\n", resp.Payload.Data)Example - Verify checksum:
import "hash/crc32"
resp, err := client.AccessSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to access secret version: %v", err)
}
if resp.Payload.DataCrc32C != nil {
actualCrc := crc32.Checksum(resp.Payload.Data, crc32.MakeTable(crc32.Castagnoli))
if int64(actualCrc) != *resp.Payload.DataCrc32C {
log.Fatal("Data corruption detected!")
}
fmt.Println("Checksum verified successfully")
}func (c *Client) GetSecretVersion(ctx context.Context, req *secretmanagerpb.GetSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)Gets metadata for a SecretVersion. This does not return the secret data - use AccessSecretVersion to get the actual payload.
Request Type:
type GetSecretVersionRequest struct {
Name string
}Fields:
Name - Required. The resource name in format projects/*/secrets/*/versions/* or projects/*/locations/*/secrets/*/versions/*Example:
req := &secretmanagerpb.GetSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/1",
}
version, err := client.GetSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to get secret version: %v", err)
}
fmt.Printf("Version: %s\n", version.Name)
fmt.Printf("State: %v\n", version.State)
fmt.Printf("Created: %s\n", version.CreateTime.AsTime())
fmt.Printf("Etag: %s\n", version.Etag)func (c *Client) ListSecretVersions(ctx context.Context, req *secretmanagerpb.ListSecretVersionsRequest, opts ...gax.CallOption) *SecretVersionIteratorLists SecretVersions. This does not return secret data - use AccessSecretVersion to retrieve the payload.
Request Type:
type ListSecretVersionsRequest struct {
Parent string
PageSize int32
PageToken string
Filter string
}Fields:
Parent - Required. The resource name in format projects/*/secrets/* or projects/*/locations/*/secrets/*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 secret versionsIterator Type:
type SecretVersionIterator struct {
Response interface{}
InternalFetch func(pageSize int, pageToken string) (results []*secretmanagerpb.SecretVersion, nextPageToken string, err error)
}Iterator Methods:
func (it *SecretVersionIterator) Next() (*secretmanagerpb.SecretVersion, error)
func (it *SecretVersionIterator) PageInfo() *iterator.PageInfo
func (it *SecretVersionIterator) All() iter.Seq2[*secretmanagerpb.SecretVersion, error]Example - List all versions:
req := &secretmanagerpb.ListSecretVersionsRequest{
Parent: "projects/my-project/secrets/my-api-key",
}
it := client.ListSecretVersions(ctx, req)
for {
version, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("failed to list versions: %v", err)
}
fmt.Printf("Version: %s, State: %v\n", version.Name, version.State)
}Example - List only enabled versions:
req := &secretmanagerpb.ListSecretVersionsRequest{
Parent: "projects/my-project/secrets/my-api-key",
Filter: "state:ENABLED",
}
it := client.ListSecretVersions(ctx, req)
for {
version, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("Enabled version: %s\n", version.Name)
}Example - Using Go 1.23+ iterator:
req := &secretmanagerpb.ListSecretVersionsRequest{
Parent: "projects/my-project/secrets/my-api-key",
}
it := client.ListSecretVersions(ctx, req)
for version, err := range it.All() {
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("Version: %s\n", version.Name)
}func (c *Client) EnableSecretVersion(ctx context.Context, req *secretmanagerpb.EnableSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)Enables a SecretVersion. Sets the state to ENABLED, allowing it to be accessed.
Request Type:
type EnableSecretVersionRequest struct {
Name string
Etag string
}Fields:
Name - Required. The resource name in format projects/*/secrets/*/versions/* or projects/*/locations/*/secrets/*/versions/*Etag - Optional. Etag of the SecretVersion for optimistic concurrency controlExample:
req := &secretmanagerpb.EnableSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/2",
}
version, err := client.EnableSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to enable secret version: %v", err)
}
fmt.Printf("Enabled version: %s, State: %v\n", version.Name, version.State)func (c *Client) DisableSecretVersion(ctx context.Context, req *secretmanagerpb.DisableSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)Disables a SecretVersion. Sets the state to DISABLED, preventing it from being accessed. Can be re-enabled with EnableSecretVersion.
Request Type:
type DisableSecretVersionRequest struct {
Name string
Etag string
}Fields:
Name - Required. The resource name in format projects/*/secrets/*/versions/* or projects/*/locations/*/secrets/*/versions/*Etag - Optional. Etag of the SecretVersion for optimistic concurrency controlExample:
req := &secretmanagerpb.DisableSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/1",
}
version, err := client.DisableSecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to disable secret version: %v", err)
}
fmt.Printf("Disabled version: %s, State: %v\n", version.Name, version.State)func (c *Client) DestroySecretVersion(ctx context.Context, req *secretmanagerpb.DestroySecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)Destroys a SecretVersion, irrevocably destroying the secret data. This action is permanent and cannot be reversed.
Request Type:
type DestroySecretVersionRequest struct {
Name string
Etag string
}Fields:
Name - Required. The resource name in format projects/*/secrets/*/versions/* or projects/*/locations/*/secrets/*/versions/*Etag - Optional. Etag of the SecretVersion for optimistic concurrency controlExample:
req := &secretmanagerpb.DestroySecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/1",
}
version, err := client.DestroySecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to destroy secret version: %v", err)
}
fmt.Printf("Destroyed version: %s\n", version.Name)
fmt.Printf("State: %v\n", version.State)
fmt.Printf("Destroy time: %s\n", version.DestroyTime.AsTime())Example with confirmation:
// Destroy is permanent, so confirm first
fmt.Print("Are you sure you want to destroy this version? (yes/no): ")
var confirm string
fmt.Scanln(&confirm)
if confirm == "yes" {
req := &secretmanagerpb.DestroySecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/1",
}
version, err := client.DestroySecretVersion(ctx, req)
if err != nil {
log.Fatalf("failed to destroy: %v", err)
}
fmt.Printf("Version destroyed: %s\n", version.Name)
} else {
fmt.Println("Destroy cancelled")
}Secret versions can be in one of three states:
type SecretVersion_State int32
const (
SecretVersion_STATE_UNSPECIFIED SecretVersion_State = 0
SecretVersion_ENABLED SecretVersion_State = 1
SecretVersion_DISABLED SecretVersion_State = 2
SecretVersion_DESTROYED SecretVersion_State = 3
)State Descriptions:
STATE_UNSPECIFIED - Not specified (unused/invalid)ENABLED - The SecretVersion may be accessedDISABLED - The SecretVersion may not be accessed but can be re-enabledDESTROYED - The SecretVersion is destroyed and cannot be recoveredState Methods:
func (SecretVersion_State) Descriptor() protoreflect.EnumDescriptor
func (x SecretVersion_State) Enum() *SecretVersion_State
func (x SecretVersion_State) Number() protoreflect.EnumNumber
func (x SecretVersion_State) String() string
func (SecretVersion_State) Type() protoreflect.EnumTypeExample - Check version state:
version, err := client.GetSecretVersion(ctx, req)
if err != nil {
log.Fatalf("error: %v", err)
}
switch version.State {
case secretmanagerpb.SecretVersion_ENABLED:
fmt.Println("Version is accessible")
case secretmanagerpb.SecretVersion_DISABLED:
fmt.Println("Version is disabled - enable it to access")
case secretmanagerpb.SecretVersion_DESTROYED:
fmt.Println("Version is permanently destroyed")
default:
fmt.Println("Unknown state")
}Secret versions can be referenced in multiple ways:
Use the version number directly:
Name: "projects/my-project/secrets/my-api-key/versions/1"Use the special identifier "latest" to always get the most recently created version:
Name: "projects/my-project/secrets/my-api-key/versions/latest"Use custom aliases defined in the secret:
// First, set up the alias in the secret
updateReq := &secretmanagerpb.UpdateSecretRequest{
Secret: &secretmanagerpb.Secret{
Name: "projects/my-project/secrets/my-api-key",
VersionAliases: map[string]int64{
"stable": 5,
},
},
UpdateMask: &fieldmaskpb.FieldMask{
Paths: []string{"version_aliases"},
},
}
client.UpdateSecret(ctx, updateReq)
// Then access using the alias
accessReq := &secretmanagerpb.AccessSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/stable",
}
resp, err := client.AccessSecretVersion(ctx, accessReq)type ListSecretVersionsResponse struct {
Versions []*SecretVersion
NextPageToken string
TotalSize int32
}Fields:
Versions - The list of SecretVersions sorted in reverse by create_timeNextPageToken - Token to retrieve the next pageTotalSize - Total number of SecretVersions (0 when filter is set)This type is used internally by the iterator and is not typically used directly.
Secret payloads must not exceed 64 KiB:
const maxPayloadSize = 64 * 1024 // 64 KiB
data := []byte("my-secret-value")
if len(data) > maxPayloadSize {
log.Fatalf("payload too large: %d bytes (max %d)", len(data), maxPayloadSize)
}
req := &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/my-project/secrets/my-api-key",
Payload: &secretmanagerpb.SecretPayload{
Data: data,
},
}Always provide CRC32C checksums when adding versions:
import "hash/crc32"
data := []byte("sensitive-data")
crc := int64(crc32.Checksum(data, crc32.MakeTable(crc32.Castagnoli)))
req := &secretmanagerpb.AddSecretVersionRequest{
Parent: parent,
Payload: &secretmanagerpb.SecretPayload{
Data: data,
DataCrc32C: &crc,
},
}Regularly rotate secrets by adding new versions:
// Add new version
newVersionReq := &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/my-project/secrets/my-api-key",
Payload: &secretmanagerpb.SecretPayload{
Data: []byte("new-rotated-value"),
},
}
newVersion, err := client.AddSecretVersion(ctx, newVersionReq)
// Update applications to use new version
// Disable old version
disableReq := &secretmanagerpb.DisableSecretVersionRequest{
Name: "projects/my-project/secrets/my-api-key/versions/1",
}
client.DisableSecretVersion(ctx, disableReq)Maintain separate aliases for different deployment stages:
// Set up aliases
updateReq := &secretmanagerpb.UpdateSecretRequest{
Secret: &secretmanagerpb.Secret{
Name: "projects/my-project/secrets/my-api-key",
VersionAliases: map[string]int64{
"production": 10,
"staging": 11,
"canary": 12,
},
},
UpdateMask: &fieldmaskpb.FieldMask{
Paths: []string{"version_aliases"},
},
}
client.UpdateSecret(ctx, updateReq)