Go Client Library for Google Cloud Secret Manager API - stores sensitive data such as API keys, passwords, and certificates
—
Identity and Access Management (IAM) controls who can access your secrets. The Secret Manager client provides methods to manage IAM policies and test permissions.
func (c *Client) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error)Sets the access control policy on the specified secret. Replaces any existing policy.
Request Type:
type SetIamPolicyRequest struct {
Resource string
Policy *Policy
UpdateMask *fieldmaskpb.FieldMask
}Fields:
Resource - Required. The resource name of the secret in format projects/*/secrets/*Policy - Required. The IAM policy to setUpdateMask - Optional. A FieldMask specifying which fields to updateExample - Grant access to a user:
import iampb "cloud.google.com/go/iam/apiv1/iampb"
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"user:alice@example.com",
"serviceAccount:my-service@my-project.iam.gserviceaccount.com",
},
},
{
Role: "roles/secretmanager.secretVersionManager",
Members: []string{
"user:bob@example.com",
},
},
},
}
req := &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
Policy: policy,
}
updatedPolicy, err := client.SetIamPolicy(ctx, req)
if err != nil {
log.Fatalf("failed to set IAM policy: %v", err)
}
fmt.Printf("Updated policy with %d bindings\n", len(updatedPolicy.Bindings))Example - Add a condition to a binding:
import (
"google.golang.org/genproto/googleapis/type/expr"
)
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"user:alice@example.com",
},
Condition: &expr.Expr{
Title: "Expires in 2025",
Description: "Access expires at the end of 2025",
Expression: "request.time < timestamp('2025-12-31T23:59:59Z')",
},
},
},
}
req := &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
Policy: policy,
}
updatedPolicy, err := client.SetIamPolicy(ctx, req)func (c *Client) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error)Gets the access control policy for a secret. Returns an empty policy if the secret does not have an explicit policy set.
Request Type:
type GetIamPolicyRequest struct {
Resource string
Options *GetPolicyOptions
}Fields:
Resource - Required. The resource name of the secret in format projects/*/secrets/*Options - Optional. Options for getting the policyExample:
req := &iampb.GetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
}
policy, err := client.GetIamPolicy(ctx, req)
if err != nil {
log.Fatalf("failed to get IAM policy: %v", err)
}
fmt.Printf("Policy version: %d\n", policy.Version)
for i, binding := range policy.Bindings {
fmt.Printf("Binding %d:\n", i)
fmt.Printf(" Role: %s\n", binding.Role)
fmt.Printf(" Members: %v\n", binding.Members)
if binding.Condition != nil {
fmt.Printf(" Condition: %s\n", binding.Condition.Expression)
}
}Example - Get policy and add a member:
// Get current policy
getReq := &iampb.GetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
}
policy, err := client.GetIamPolicy(ctx, getReq)
if err != nil {
log.Fatalf("failed to get policy: %v", err)
}
// Find or create binding for the role
var binding *iampb.Binding
for _, b := range policy.Bindings {
if b.Role == "roles/secretmanager.secretAccessor" {
binding = b
break
}
}
if binding == nil {
binding = &iampb.Binding{
Role: "roles/secretmanager.secretAccessor",
Members: []string{},
}
policy.Bindings = append(policy.Bindings, binding)
}
// Add new member
newMember := "user:charlie@example.com"
binding.Members = append(binding.Members, newMember)
// Update policy
setReq := &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
Policy: policy,
}
updatedPolicy, err := client.SetIamPolicy(ctx, setReq)
if err != nil {
log.Fatalf("failed to update policy: %v", err)
}
fmt.Printf("Added member: %s\n", newMember)func (c *Client) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error)Returns permissions that a caller has for the specified secret. If the secret does not exist, this will return an empty set of permissions.
Request Type:
type TestIamPermissionsRequest struct {
Resource string
Permissions []string
}Fields:
Resource - Required. The resource name of the secret in format projects/*/secrets/*Permissions - Required. The set of permissions to checkResponse Type:
type TestIamPermissionsResponse struct {
Permissions []string
}Fields:
Permissions - A subset of TestIamPermissionsRequest.permissions that the caller is allowedExample:
req := &iampb.TestIamPermissionsRequest{
Resource: "projects/my-project/secrets/my-api-key",
Permissions: []string{
"secretmanager.secrets.get",
"secretmanager.secrets.update",
"secretmanager.versions.access",
},
}
resp, err := client.TestIamPermissions(ctx, req)
if err != nil {
log.Fatalf("failed to test permissions: %v", err)
}
fmt.Printf("Granted permissions: %v\n", resp.Permissions)
// Check specific permission
hasAccessPermission := false
for _, perm := range resp.Permissions {
if perm == "secretmanager.versions.access" {
hasAccessPermission = true
break
}
}
if hasAccessPermission {
fmt.Println("User can access secret versions")
} else {
fmt.Println("User cannot access secret versions")
}func (c *Client) IAM(name string) *iam.HandleReturns a handle to inspect and change permissions of the resource indicated by the given secret name. The handle provides a more ergonomic interface for IAM operations.
Example:
import "cloud.google.com/go/iam"
handle := client.IAM("projects/my-project/secrets/my-api-key")
// Get current policy
policy, err := handle.Policy(ctx)
if err != nil {
log.Fatalf("failed to get policy: %v", err)
}
// Add a member to a role
policy.Add("user:dave@example.com", "roles/secretmanager.secretAccessor")
// Update the policy
if err := handle.SetPolicy(ctx, policy); err != nil {
log.Fatalf("failed to set policy: %v", err)
}
fmt.Println("Successfully updated IAM policy")Example - Test permissions using handle:
handle := client.IAM("projects/my-project/secrets/my-api-key")
permissions := []string{
"secretmanager.secrets.get",
"secretmanager.versions.access",
}
allowed, err := handle.TestPermissions(ctx, permissions)
if err != nil {
log.Fatalf("failed to test permissions: %v", err)
}
fmt.Printf("Allowed permissions: %v\n", allowed)Secret Manager provides predefined roles for common access patterns:
Full access to all Secret Manager resources.
Permissions:
Example:
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.admin",
Members: []string{
"user:admin@example.com",
},
},
},
}Read access to secret versions (the actual secret data).
Permissions:
secretmanager.versions.access - Access secret version payloadssecretmanager.versions.get - Get secret version metadatasecretmanager.versions.list - List secret versionssecretmanager.secrets.get - Get secret metadatasecretmanager.secrets.list - List secretsExample:
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:my-app@my-project.iam.gserviceaccount.com",
},
},
},
}Manage secret versions without accessing secret data.
Permissions:
secretmanager.versions.accessExample:
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretVersionManager",
Members: []string{
"user:rotation-bot@example.com",
},
},
},
}Read-only access to secret metadata (not secret data).
Permissions:
secretmanager.versions.accessExample:
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.viewer",
Members: []string{
"group:auditors@example.com",
},
},
},
}secretmanager.secrets.create - Create new secretssecretmanager.secrets.delete - Delete secretssecretmanager.secrets.get - Get secret metadatasecretmanager.secrets.list - List secretssecretmanager.secrets.update - Update secret metadatasecretmanager.secrets.getIamPolicy - Get IAM policysecretmanager.secrets.setIamPolicy - Set IAM policysecretmanager.versions.access - Access secret version datasecretmanager.versions.add - Add new secret versionssecretmanager.versions.destroy - Destroy secret versionssecretmanager.versions.disable - Disable secret versionssecretmanager.versions.enable - Enable secret versionssecretmanager.versions.get - Get secret version metadatasecretmanager.versions.list - List secret versionsGrant only the minimum permissions needed:
// Good: Application only needs to read secrets
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:app@my-project.iam.gserviceaccount.com",
},
},
},
}
// Bad: Application granted admin access
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.admin",
Members: []string{
"serviceAccount:app@my-project.iam.gserviceaccount.com",
},
},
},
}Applications should use service accounts instead of user credentials:
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:web-app@my-project.iam.gserviceaccount.com",
"serviceAccount:worker@my-project.iam.gserviceaccount.com",
},
},
},
}Grant temporary access using IAM conditions:
import "google.golang.org/genproto/googleapis/type/expr"
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"user:contractor@example.com",
},
Condition: &expr.Expr{
Title: "Temporary access",
Description: "Access expires on January 31, 2025",
Expression: "request.time < timestamp('2025-01-31T23:59:59Z')",
},
},
},
}Use different secrets for different environments:
// Production secret - strict access
prodPolicy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:prod-app@my-project.iam.gserviceaccount.com",
},
},
},
}
prodReq := &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/api-key-prod",
Policy: prodPolicy,
}
client.SetIamPolicy(ctx, prodReq)
// Development secret - broader access
devPolicy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:dev-app@my-project.iam.gserviceaccount.com",
"group:developers@example.com",
},
},
},
}
devReq := &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/api-key-dev",
Policy: devPolicy,
}
client.SetIamPolicy(ctx, devReq)Log IAM policy changes for security auditing:
// Get current policy for audit log
oldPolicy, err := client.GetIamPolicy(ctx, &iampb.GetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
})
// Update policy
newPolicy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{"user:new-user@example.com"},
},
},
}
updatedPolicy, err := client.SetIamPolicy(ctx, &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-api-key",
Policy: newPolicy,
})
// Log the change
log.Printf("IAM policy updated for secret my-api-key")
log.Printf("Old bindings: %v", oldPolicy.Bindings)
log.Printf("New bindings: %v", updatedPolicy.Bindings)IAM members can be specified in various formats:
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
// Individual user
"user:alice@example.com",
// Service account
"serviceAccount:my-service@my-project.iam.gserviceaccount.com",
// Google group
"group:developers@example.com",
// Google Workspace domain
"domain:example.com",
// All authenticated users
"allAuthenticatedUsers",
// All users (public access - use with caution!)
"allUsers",
},
},
},
}Warning: Never use allUsers for secrets containing sensitive data. This grants public access to anyone on the internet.
Install with Tessl CLI
npx tessl i tessl/golang-cloud-google-com--go--secretmanager