Google Cloud Storage client library for Go providing comprehensive APIs for bucket and object operations, access control, and advanced features
—
This document covers access control mechanisms including Access Control Lists (ACLs), IAM policies, signed URLs for time-limited access, and POST policies for browser-based uploads.
Manage fine-grained access control for buckets and objects.
/**
* ACLHandle provides operations on an access control list.
* Use BucketHandle.ACL() for bucket ACLs.
* Use BucketHandle.DefaultObjectACL() for default object ACLs.
* Use ObjectHandle.ACL() for object ACLs.
*/
type ACLHandle struct {
// contains filtered or unexported fields
}
/**
* Lists all ACL rules.
* @param ctx - Context for the operation
* @returns Slice of ACLRule and error
*/
func (a *ACLHandle) List(ctx context.Context) ([]ACLRule, error)
/**
* Sets the role for an entity.
* @param ctx - Context for the operation
* @param entity - ACL entity (user, group, domain, etc.)
* @param role - ACL role (OWNER, READER, WRITER)
* @returns Error if set fails
*/
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) error
/**
* Deletes the ACL entry for an entity.
* @param ctx - Context for the operation
* @param entity - ACL entity to delete
* @returns Error if delete fails
*/
func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) errorTypes for defining access control rules.
/**
* ACLEntity refers to a user or group (grantee).
* Can be in the form of:
* - "user-<userId>" or "user-<email>"
* - "group-<groupId>" or "group-<email>"
* - "domain-<domain>"
* - "project-team-<projectId>"
* - Predefined: AllUsers, AllAuthenticatedUsers
*/
type ACLEntity string
/**
* ACLRole is the level of access to grant.
*/
type ACLRole string
// Predefined ACL entities
const (
// AllUsers grants access to anyone on the internet
AllUsers ACLEntity = "allUsers"
// AllAuthenticatedUsers grants access to any authenticated user
AllAuthenticatedUsers ACLEntity = "allAuthenticatedUsers"
)
// ACL roles
const (
// RoleOwner grants full control
RoleOwner ACLRole = "OWNER"
// RoleReader grants read access
RoleReader ACLRole = "READER"
// RoleWriter grants write access (buckets only)
RoleWriter ACLRole = "WRITER"
)
/**
* ACLRule represents a grant for a role to an entity.
*/
type ACLRule struct {
// Entity is the grantee (user, group, domain, etc.)
Entity ACLEntity
// EntityID is the ID for the entity (read-only)
EntityID string
// Role is the access level granted
Role ACLRole
// Domain is the domain for domain entities (read-only)
Domain string
// Email is the email for user/group entities (read-only)
Email string
// ProjectTeam is the project team info (read-only)
ProjectTeam *ProjectTeam
}
/**
* ProjectTeam is the project team associated with an entity.
*/
type ProjectTeam struct {
// ProjectNumber is the project number
ProjectNumber string
// Team is the team name (editors, owners, viewers)
Team string
}Usage Examples:
import (
"context"
"cloud.google.com/go/storage"
)
ctx := context.Background()
bucket := client.Bucket("my-bucket")
// List bucket ACL
rules, err := bucket.ACL().List(ctx)
if err != nil {
log.Fatal(err)
}
for _, rule := range rules {
fmt.Printf("Entity: %s, Role: %s\n", rule.Entity, rule.Role)
}
// Grant read access to a user
entity := storage.ACLEntity("user-alice@example.com")
err = bucket.ACL().Set(ctx, entity, storage.RoleReader)
if err != nil {
log.Fatal(err)
}
// Grant public read access
err = bucket.ACL().Set(ctx, storage.AllUsers, storage.RoleReader)
if err != nil {
log.Fatal(err)
}
// Revoke access
err = bucket.ACL().Delete(ctx, entity)
if err != nil {
log.Fatal(err)
}
// Set object ACL
obj := bucket.Object("my-object.txt")
err = obj.ACL().Set(ctx, storage.AllAuthenticatedUsers, storage.RoleReader)
// Set default object ACL (applied to new objects)
err = bucket.DefaultObjectACL().Set(ctx, storage.AllUsers, storage.RoleReader)Manage Identity and Access Management policies for buckets.
/**
* Returns an IAM handle for the bucket.
* IAM policies provide centralized access control.
* @returns iam.Handle for policy management
*/
func (b *BucketHandle) IAM() *iam.HandleNote: The IAM handle comes from cloud.google.com/go/iam package. Common IAM operations:
import (
"cloud.google.com/go/iam"
"cloud.google.com/go/iam/apiv1/iampb"
)
// Get IAM policy
handle := bucket.IAM()
policy, err := handle.Policy(ctx)
if err != nil {
log.Fatal(err)
}
// Add a member to a role
policy.Add("user:alice@example.com", "roles/storage.objectViewer")
// Set the updated policy
err = handle.SetPolicy(ctx, policy)
if err != nil {
log.Fatal(err)
}
// Test permissions
permissions := []string{
"storage.objects.get",
"storage.objects.list",
}
allowed, err := handle.TestPermissions(ctx, permissions)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Allowed permissions: %v\n", allowed)Generate time-limited URLs for restricted resource access without authentication.
/**
* Generates a signed URL for restricted resource access.
* Allows unauthenticated access for a limited time.
* @param bucket - Bucket name
* @param object - Object name
* @param opts - Signed URL options
* @returns Signed URL string and error
*/
func SignedURL(bucket, object string, opts *SignedURLOptions) (string, error)
/**
* Generates a signed URL via the bucket handle.
* Supports automatic credential detection.
* @param object - Object name
* @param opts - Signed URL options
* @returns Signed URL string and error
*/
func (b *BucketHandle) SignedURL(object string, opts *SignedURLOptions) (string, error)
/**
* SignedURLOptions configures signed URL generation.
*/
type SignedURLOptions struct {
// GoogleAccessID is the service account email address
// Required (unless auto-detected)
GoogleAccessID string
// PrivateKey is the service account private key (PEM format)
// Exactly one of PrivateKey or SignBytes must be provided
PrivateKey []byte
// SignBytes is a custom signing function
// Exactly one of PrivateKey or SignBytes must be provided
SignBytes func([]byte) ([]byte, error)
// Method is the HTTP method for the signed URL
// Valid values: GET, HEAD, PUT, POST, DELETE
// Required
Method string
// Expires is the expiration time
// Must be in the future
// For V4, maximum 7 days from now
// Required
Expires time.Time
// ContentType is the required Content-Type header
// Optional
ContentType string
// Headers are additional required headers
// Optional
Headers []string
// QueryParameters are additional query parameters
// Optional
QueryParameters url.Values
// MD5 is the required MD5 hash (base64-encoded)
// Optional
MD5 string
// Style configures the URL style
// Use URLStyle functions: PathStyle(), VirtualHostedStyle(), BucketBoundHostname()
// Optional
Style *URLStyle
// Insecure allows HTTP instead of HTTPS
// Not recommended for production
// Optional
Insecure bool
// Scheme is the signing scheme (V2 or V4)
// V4 is recommended
// Optional (defaults to V2 for compatibility)
Scheme SigningScheme
// Hostname is a custom hostname for the URL
// Optional (defaults to storage.googleapis.com)
Hostname string
}
/**
* SigningScheme determines the version of signed URL.
*/
type SigningScheme int
const (
// SigningSchemeV2 uses V2 signing (deprecated)
SigningSchemeV2 SigningScheme = iota
// SigningSchemeV4 uses V4 signing (recommended)
SigningSchemeV4
)
/**
* URLStyle configures the URL format.
*/
type URLStyle struct {
// contains filtered or unexported fields
}
/**
* Returns path-style URL configuration.
* Format: https://storage.googleapis.com/bucket/object
* @returns URLStyle for path-style URLs
*/
func PathStyle() *URLStyle
/**
* Returns virtual-hosted-style URL configuration.
* Format: https://bucket.storage.googleapis.com/object
* @returns URLStyle for virtual-hosted-style URLs
*/
func VirtualHostedStyle() *URLStyle
/**
* Returns custom hostname URL configuration.
* Format: https://custom.example.com/object
* @param hostname - Custom hostname
* @returns URLStyle for custom hostname URLs
*/
func BucketBoundHostname(hostname string) *URLStyleUsage Examples:
import (
"time"
"cloud.google.com/go/storage"
)
// Generate signed URL for download (GET)
opts := &storage.SignedURLOptions{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes, // Load from key file
Method: "GET",
Expires: time.Now().Add(15 * time.Minute),
}
url, err := storage.SignedURL("my-bucket", "my-object.txt", opts)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Download URL: %s\n", url)
// Generate signed URL for upload (PUT)
opts = &storage.SignedURLOptions{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Method: "PUT",
Expires: time.Now().Add(1 * time.Hour),
ContentType: "image/jpeg",
}
url, err = storage.SignedURL("my-bucket", "upload.jpg", opts)
// Use V4 signing (recommended)
opts = &storage.SignedURLOptions{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Method: "GET",
Expires: time.Now().Add(24 * time.Hour),
Scheme: storage.SigningSchemeV4,
}
url, err = storage.SignedURL("my-bucket", "my-object.txt", opts)
// Use virtual-hosted-style URL
opts = &storage.SignedURLOptions{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Method: "GET",
Expires: time.Now().Add(1 * time.Hour),
Style: storage.VirtualHostedStyle(),
}
url, err = storage.SignedURL("my-bucket", "my-object.txt", opts)
// Use custom hostname
opts = &storage.SignedURLOptions{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Method: "GET",
Expires: time.Now().Add(1 * time.Hour),
Style: storage.BucketBoundHostname("cdn.example.com"),
}
url, err = storage.SignedURL("my-bucket", "my-object.txt", opts)
// Auto-detect credentials (using bucket handle)
bucket := client.Bucket("my-bucket")
opts = &storage.SignedURLOptions{
Method: "GET",
Expires: time.Now().Add(15 * time.Minute),
}
url, err = bucket.SignedURL("my-object.txt", opts)
// GoogleAccessID and PrivateKey are auto-detected from client credentials
// With custom signing function (e.g., for App Engine)
opts = &storage.SignedURLOptions{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
SignBytes: func(b []byte) ([]byte, error) {
// Custom signing logic (e.g., using KMS, HSM, etc.)
return signFunction(b)
},
Method: "GET",
Expires: time.Now().Add(1 * time.Hour),
}
url, err = storage.SignedURL("my-bucket", "my-object.txt", opts)Generate POST policies for browser-based file uploads.
/**
* Generates a PostPolicyV4 for browser-based uploads.
* Allows unauthenticated multipart form uploads.
* @param bucket - Bucket name
* @param object - Object name (empty string with prefix condition for variable names)
* @param opts - POST policy options
* @returns PostPolicyV4 and error
*/
func GenerateSignedPostPolicyV4(bucket, object string, opts *PostPolicyV4Options) (*PostPolicyV4, error)
/**
* Generates a PostPolicyV4 via the bucket handle.
* Supports automatic credential detection.
* @param object - Object name
* @param opts - POST policy options
* @returns PostPolicyV4 and error
*/
func (b *BucketHandle) GenerateSignedPostPolicyV4(object string, opts *PostPolicyV4Options) (*PostPolicyV4, error)
/**
* PostPolicyV4Options configures POST policy generation.
*/
type PostPolicyV4Options struct {
// GoogleAccessID is the service account email address
// Required (unless auto-detected)
GoogleAccessID string
// PrivateKey is the service account private key (PEM format)
// Exactly one of PrivateKey, SignBytes, or SignRawBytes must be provided
PrivateKey []byte
// SignBytes is a custom signing function
SignBytes func([]byte) ([]byte, error)
// SignRawBytes is a custom raw signing function
SignRawBytes func([]byte) ([]byte, error)
// Expires is the expiration time
// Must be in the future, maximum 7 days from now
// Required
Expires time.Time
// Fields are form fields to include in the policy
// Optional
Fields *PolicyV4Fields
// Conditions are policy conditions
// Optional
Conditions []PostPolicyV4Condition
// Hostname is a custom hostname
// Optional (defaults to storage.googleapis.com)
Hostname string
// Style configures the URL style
// Optional
Style *URLStyle
}
/**
* PolicyV4Fields contains form fields for the POST form.
*/
type PolicyV4Fields struct {
// ACL is the access control list
ACL string
// CacheControl is the Cache-Control header
CacheControl string
// ContentType is the Content-Type header
ContentType string
// ContentDisposition is the Content-Disposition header
ContentDisposition string
// ContentEncoding is the Content-Encoding header
ContentEncoding string
// Expires is the Expires header
Expires time.Time
// SuccessActionRedirect is the redirect URL after successful upload
SuccessActionRedirect string
// SuccessActionStatus is the HTTP status code to return after successful upload
SuccessActionStatus int
// Metadata is custom metadata
Metadata map[string]string
}
/**
* PostPolicyV4Condition represents a policy condition.
*/
type PostPolicyV4Condition interface {
// contains filtered or unexported methods
}
/**
* Creates a condition that a field starts with a prefix.
* @param key - Form field name
* @param prefix - Required prefix
* @returns PostPolicyV4Condition
*/
func ConditionStartsWith(key, prefix string) PostPolicyV4Condition
/**
* Creates a content-length range condition.
* @param start - Minimum length in bytes
* @param end - Maximum length in bytes
* @returns PostPolicyV4Condition
*/
func ConditionContentLengthRange(start, end uint64) PostPolicyV4Condition
/**
* PostPolicyV4 contains the generated POST policy.
*/
type PostPolicyV4 struct {
// URL is the form action URL
URL string
// Fields are the hidden form fields to include
Fields map[string]string
}Usage Examples:
import (
"time"
"cloud.google.com/go/storage"
)
// Generate POST policy for file upload
opts := &storage.PostPolicyV4Options{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Expires: time.Now().Add(30 * time.Minute),
}
policy, err := storage.GenerateSignedPostPolicyV4("my-bucket", "upload.jpg", opts)
if err != nil {
log.Fatal(err)
}
// Use in HTML form
html := fmt.Sprintf(`
<form action="%s" method="post" enctype="multipart/form-data">
<input type="hidden" name="key" value="%s">
<input type="hidden" name="x-goog-signature" value="%s">
<input type="hidden" name="x-goog-algorithm" value="%s">
<input type="hidden" name="x-goog-credential" value="%s">
<input type="hidden" name="x-goog-date" value="%s">
<input type="hidden" name="policy" value="%s">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
`, policy.URL, policy.Fields["key"], policy.Fields["x-goog-signature"],
policy.Fields["x-goog-algorithm"], policy.Fields["x-goog-credential"],
policy.Fields["x-goog-date"], policy.Fields["policy"])
// POST policy with metadata
opts = &storage.PostPolicyV4Options{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Expires: time.Now().Add(1 * time.Hour),
Fields: &storage.PolicyV4Fields{
ContentType: "image/jpeg",
Metadata: map[string]string{
"uploaded-by": "web-form",
},
},
}
policy, err = storage.GenerateSignedPostPolicyV4("my-bucket", "photo.jpg", opts)
// POST policy with conditions
opts = &storage.PostPolicyV4Options{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Expires: time.Now().Add(1 * time.Hour),
Conditions: []storage.PostPolicyV4Condition{
storage.ConditionContentLengthRange(0, 10*1024*1024), // Max 10MB
storage.ConditionStartsWith("$key", "uploads/"),
},
}
policy, err = storage.GenerateSignedPostPolicyV4("my-bucket", "", opts)
// POST policy with variable object name
opts = &storage.PostPolicyV4Options{
GoogleAccessID: "service-account@project.iam.gserviceaccount.com",
PrivateKey: privateKeyBytes,
Expires: time.Now().Add(1 * time.Hour),
Conditions: []storage.PostPolicyV4Condition{
storage.ConditionStartsWith("$key", "user-uploads/"),
},
}
// Empty object name allows any name matching conditions
policy, err = storage.GenerateSignedPostPolicyV4("my-bucket", "", opts)
// Auto-detect credentials (using bucket handle)
bucket := client.Bucket("my-bucket")
opts = &storage.PostPolicyV4Options{
Expires: time.Now().Add(30 * time.Minute),
Fields: &storage.PolicyV4Fields{
ContentType: "text/plain",
},
}
policy, err = bucket.GenerateSignedPostPolicyV4("upload.txt", opts)HMAC keys for S3-compatible authentication.
/**
* Creates a new HMAC key for the service account.
* @param ctx - Context for the operation
* @param projectID - Google Cloud project ID
* @param serviceAccountEmail - Service account email
* @param opts - Optional HMAC key options
* @returns HMACKey and error
*/
func (c *Client) CreateHMACKey(ctx context.Context, projectID, serviceAccountEmail string, opts ...HMACKeyOption) (*HMACKey, error)
/**
* Returns a handle to an HMAC key.
* @param projectID - Google Cloud project ID
* @param accessID - HMAC key access ID
* @returns HMACKeyHandle
*/
func (c *Client) HMACKeyHandle(projectID, accessID string) *HMACKeyHandle
/**
* Returns an iterator over HMAC keys.
* @param ctx - Context for the operation
* @param projectID - Google Cloud project ID
* @param opts - Optional filter options
* @returns HMACKeysIterator
*/
func (c *Client) ListHMACKeys(ctx context.Context, projectID string, opts ...HMACKeyOption) *HMACKeysIterator
/**
* HMACKey contains HMAC key information.
*/
type HMACKey struct {
// Secret is the secret key (only returned on creation)
Secret string
// AccessID is the access ID (public)
AccessID string
// Etag is the entity tag (read-only)
Etag string
// ID is the HMAC key identifier
ID string
// ProjectID is the project ID
ProjectID string
// ServiceAccountEmail is the service account email
ServiceAccountEmail string
// CreatedTime is the creation time (read-only)
CreatedTime time.Time
// UpdatedTime is the last update time (read-only)
UpdatedTime time.Time
// State is the key state (Active, Inactive, Deleted)
State HMACState
}
/**
* HMACKeyHandle provides operations on an HMAC key.
*/
type HMACKeyHandle struct {
// contains filtered or unexported fields
}
/**
* Retrieves the HMAC key metadata.
* @param ctx - Context for the operation
* @param opts - Optional HMAC key options
* @returns HMACKey and error
*/
func (h *HMACKeyHandle) Get(ctx context.Context, opts ...HMACKeyOption) (*HMACKey, error)
/**
* Updates the HMAC key.
* @param ctx - Context for the operation
* @param attrs - Attributes to update
* @param opts - Optional HMAC key options
* @returns Updated HMACKey and error
*/
func (h *HMACKeyHandle) Update(ctx context.Context, attrs HMACKeyAttrsToUpdate, opts ...HMACKeyOption) (*HMACKey, error)
/**
* Deletes the HMAC key.
* Key must be inactive before deletion.
* @param ctx - Context for the operation
* @param opts - Optional HMAC key options
* @returns Error if deletion fails
*/
func (h *HMACKeyHandle) Delete(ctx context.Context, opts ...HMACKeyOption) error
/**
* HMACKeyAttrsToUpdate specifies HMAC key attributes to update.
*/
type HMACKeyAttrsToUpdate struct {
// State is the key state to set
// Valid values: Active, Inactive
State HMACState
// Etag is the entity tag for concurrency control
Etag string
}
/**
* HMACState represents the state of an HMAC key.
*/
type HMACState string
const (
// Active key state
Active HMACState = "ACTIVE"
// Inactive key state
Inactive HMACState = "INACTIVE"
// Deleted key state (read-only)
Deleted HMACState = "DELETED"
)
/**
* HMACKeysIterator is an iterator over HMAC keys.
*/
type HMACKeysIterator struct {
// contains filtered or unexported fields
}
/**
* Returns the next HMAC key. Returns iterator.Done when complete.
* @returns HMACKey and error
*/
func (it *HMACKeysIterator) Next() (*HMACKey, error)
/**
* Returns pagination information.
* @returns iterator.PageInfo
*/
func (it *HMACKeysIterator) PageInfo() *iterator.PageInfo
/**
* HMACKeyOption configures HMAC key operations.
*/
type HMACKeyOption interface {
// contains filtered or unexported methods
}
/**
* Filters HMAC keys by service account.
* @param email - Service account email
* @returns HMACKeyOption
*/
func ForHMACKeyServiceAccountEmail(email string) HMACKeyOption
/**
* Includes deleted keys in listing.
* @returns HMACKeyOption
*/
func ShowDeletedHMACKeys() HMACKeyOption
/**
* Bills HMAC key requests against the specified user project.
* @param userProjectID - Project ID to bill
* @returns HMACKeyOption
*/
func UserProjectForHMACKeys(userProjectID string) HMACKeyOptionUsage Examples:
import (
"cloud.google.com/go/storage"
"google.golang.org/api/iterator"
)
ctx := context.Background()
// Create HMAC key
key, err := client.CreateHMACKey(ctx, "my-project", "service-account@my-project.iam.gserviceaccount.com")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Access ID: %s\n", key.AccessID)
fmt.Printf("Secret: %s\n", key.Secret) // Only available on creation
fmt.Printf("State: %s\n", key.State)
// List HMAC keys
it := client.ListHMACKeys(ctx, "my-project")
for {
key, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("Key: %s, State: %s\n", key.AccessID, key.State)
}
// List keys for specific service account
it = client.ListHMACKeys(ctx, "my-project",
storage.ForHMACKeyServiceAccountEmail("service-account@my-project.iam.gserviceaccount.com"))
// Get HMAC key
handle := client.HMACKeyHandle("my-project", "access-id")
key, err = handle.Get(ctx)
if err != nil {
log.Fatal(err)
}
// Deactivate HMAC key
update := storage.HMACKeyAttrsToUpdate{
State: storage.Inactive,
}
key, err = handle.Update(ctx, update)
if err != nil {
log.Fatal(err)
}
// Delete HMAC key (must be inactive first)
err = handle.Delete(ctx)
if err != nil {
log.Fatal(err)
}
// List including deleted keys
it = client.ListHMACKeys(ctx, "my-project", storage.ShowDeletedHMACKeys())Install with Tessl CLI
npx tessl i tessl/golang-cloud-google-com-go-storage