This document covers AWS SDK for Go v2 S3 bucket access control operations including ACLs, bucket policies, public access blocks, ownership controls, and ABAC (Attribute-Based Access Control).
github.com/aws/aws-sdk-go-v2/service/s3github.com/aws/aws-sdk-go-v2/service/s3/typesRetrieves the access control list (ACL) of a bucket.
Note: Not supported for directory buckets. Beginning November 21, 2025, Amazon S3 will stop returning DisplayName. Use canonical IDs, AWS account IDs, or IAM ARNs instead.
func (c *Client) GetBucketAcl(
ctx context.Context,
params *GetBucketAclInput,
optFns ...func(*Options),
) (*GetBucketAclOutput, error)type GetBucketAclInput struct {
// Specifies the S3 bucket whose ACL is being requested.
// When using with an access point, provide the alias of the access point.
// When using with an Object Lambda access point, provide the alias of the
// Object Lambda access point.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner. If the account ID that you
// provide does not match the actual owner of the bucket, the request fails
// with the HTTP status code 403 Forbidden (access denied).
// Required: No
ExpectedBucketOwner *string
}type GetBucketAclOutput struct {
// A list of grants.
Grants []types.Grant
// Container for the bucket owner's display name and ID.
Owner *types.Owner
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}Grant { .api }
type Grant struct {
// The person being granted permissions.
Grantee *Grantee
// Specifies the permission given to the grantee.
// Values: READ | WRITE | READ_ACP | WRITE_ACP | FULL_CONTROL
Permission Permission
}Grantee { .api }
type Grantee struct {
// Type of grantee
// Required: Yes
// Values: CanonicalUser | AmazonCustomerByEmail | Group
Type Type
// Screen name of the grantee (deprecated in some regions).
DisplayName *string
// Email address of the grantee (only supported in specific regions).
EmailAddress *string
// The canonical user ID of the grantee.
ID *string
// URI of the grantee group.
URI *string
}Owner { .api }
type Owner struct {
// Container for the display name of the owner (supported in specific regions only).
DisplayName *string
// Container for the ID of the owner.
ID *string
}package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
output, err := client.GetBucketAcl(context.TODO(), &s3.GetBucketAclInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Owner: %s\n", *output.Owner.ID)
for _, grant := range output.Grants {
fmt.Printf("Grantee: %s, Permission: %s\n",
*grant.Grantee.ID, grant.Permission)
}
}Sets the permissions on an existing bucket using access control lists (ACL).
Note: Not supported for directory buckets. Email grantee support discontinued after October 1, 2025. If your bucket uses bucket owner enforced setting, ACLs are disabled and no longer affect permissions.
func (c *Client) PutBucketAcl(
ctx context.Context,
params *PutBucketAclInput,
optFns ...func(*Options),
) (*PutBucketAclOutput, error)type PutBucketAclInput struct {
// The bucket to which to apply the ACL.
// Required: Yes
Bucket *string
// The canned ACL to apply to the bucket.
// Values: private | public-read | public-read-write | authenticated-read
// Required: No
ACL types.BucketCannedACL
// Contains the elements that set the ACL permissions for an object per grantee.
// Required: No
AccessControlPolicy *types.AccessControlPolicy
// Indicates the algorithm used to create the checksum for the request when
// you use the SDK. Values: CRC32 | CRC32C | SHA1 | SHA256
// Required: No
ChecksumAlgorithm types.ChecksumAlgorithm
// The Base64 encoded 128-bit MD5 digest of the data.
// Required: No
ContentMD5 *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
// Allows grantee the read, write, read ACP, and write ACP permissions on the bucket.
// Format: id="canonical-user-id"
// Required: No
GrantFullControl *string
// Allows grantee to list the objects in the bucket.
// Format: id="canonical-user-id" or uri="http://acs.amazonaws.com/groups/..."
// Required: No
GrantRead *string
// Allows grantee to read the bucket ACL.
// Format: id="canonical-user-id"
// Required: No
GrantReadACP *string
// Allows grantee to create new objects in the bucket.
// Format: id="canonical-user-id"
// Required: No
GrantWrite *string
// Allows grantee to write the ACL for the applicable bucket.
// Format: id="canonical-user-id"
// Required: No
GrantWriteACP *string
}AccessControlPolicy { .api }
type AccessControlPolicy struct {
// A list of grants.
Grants []Grant
// Container for the bucket owner's display name and ID.
Owner *Owner
}type PutBucketAclOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Example 1: Using canned ACL
_, err = client.PutBucketAcl(context.TODO(), &s3.PutBucketAclInput{
Bucket: aws.String("my-bucket"),
ACL: types.BucketCannedACLPrivate,
})
if err != nil {
log.Fatal(err)
}
// Example 2: Using grant headers
_, err = client.PutBucketAcl(context.TODO(), &s3.PutBucketAclInput{
Bucket: aws.String("my-bucket"),
GrantRead: aws.String("id=canonical-user-id"),
GrantReadACP: aws.String("id=canonical-user-id"),
})
if err != nil {
log.Fatal(err)
}
// Example 3: Using AccessControlPolicy
_, err = client.PutBucketAcl(context.TODO(), &s3.PutBucketAclInput{
Bucket: aws.String("my-bucket"),
AccessControlPolicy: &types.AccessControlPolicy{
Owner: &types.Owner{
ID: aws.String("owner-canonical-user-id"),
},
Grants: []types.Grant{
{
Grantee: &types.Grantee{
Type: types.TypeCanonicalUser,
ID: aws.String("grantee-canonical-user-id"),
},
Permission: types.PermissionRead,
},
},
},
})
if err != nil {
log.Fatal(err)
}
}Returns the policy of a specified bucket.
Note: For directory buckets, you must use path-style requests to the Regional endpoint and the s3express:GetBucketPolicy permission.
func (c *Client) GetBucketPolicy(
ctx context.Context,
params *GetBucketPolicyInput,
optFns ...func(*Options),
) (*GetBucketPolicyOutput, error)type GetBucketPolicyInput struct {
// The bucket name to get the bucket policy for.
// For directory buckets, use path-style requests.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Not supported for directory buckets.
// Required: No
ExpectedBucketOwner *string
}type GetBucketPolicyOutput struct {
// The bucket policy as a JSON document.
Policy *string
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
output, err := client.GetBucketPolicy(context.TODO(), &s3.GetBucketPolicyInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Bucket Policy:\n%s\n", *output.Policy)
}Applies an Amazon S3 bucket policy to an Amazon S3 bucket.
Note: For directory buckets, only the s3express:CreateSession IAM action is supported in the bucket policy.
func (c *Client) PutBucketPolicy(
ctx context.Context,
params *PutBucketPolicyInput,
optFns ...func(*Options),
) (*PutBucketPolicyOutput, error)type PutBucketPolicyInput struct {
// The name of the bucket.
// For directory buckets, use path-style requests.
// Required: Yes
Bucket *string
// The bucket policy as a JSON document.
// For directory buckets, only s3express:CreateSession is supported.
// Required: Yes
Policy *string
// Indicates the algorithm used to create the checksum.
// Values: CRC32 | CRC32C | CRC64NVME | SHA1 | SHA256
// Required: No
ChecksumAlgorithm types.ChecksumAlgorithm
// Set to true to confirm that you want to remove your permissions to change
// this bucket policy in the future.
// Not supported for directory buckets.
// Required: No
ConfirmRemoveSelfBucketAccess *bool
// The MD5 hash of the request body.
// Not supported for directory buckets.
// Required: No
ContentMD5 *string
// The account ID of the expected bucket owner.
// Not supported for directory buckets.
// Required: No
ExpectedBucketOwner *string
}type PutBucketPolicyOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"encoding/json"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Example 1: Public read policy
publicReadPolicy := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
},
},
}
policyJSON, err := json.Marshal(publicReadPolicy)
if err != nil {
log.Fatal(err)
}
_, err = client.PutBucketPolicy(context.TODO(), &s3.PutBucketPolicyInput{
Bucket: aws.String("my-bucket"),
Policy: aws.String(string(policyJSON)),
})
if err != nil {
log.Fatal(err)
}
// Example 2: Restrict access to specific VPC
vpcPolicy := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Sid": "Access-to-specific-VPC-only",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": []string{
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*",
},
"Condition": map[string]interface{}{
"StringNotEquals": map[string]string{
"aws:SourceVpc": "vpc-111bbb22",
},
},
},
},
}
vpcPolicyJSON, err := json.Marshal(vpcPolicy)
if err != nil {
log.Fatal(err)
}
_, err = client.PutBucketPolicy(context.TODO(), &s3.PutBucketPolicyInput{
Bucket: aws.String("my-bucket"),
Policy: aws.String(string(vpcPolicyJSON)),
})
if err != nil {
log.Fatal(err)
}
// Example 3: Require MFA for delete operations
mfaPolicy := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Sid": "RequireMFAForDelete",
"Effect": "Deny",
"Principal": "*",
"Action": []string{
"s3:DeleteObject",
"s3:DeleteObjectVersion",
},
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": map[string]interface{}{
"BoolIfExists": map[string]string{
"aws:MultiFactorAuthPresent": "false",
},
},
},
},
}
mfaPolicyJSON, err := json.Marshal(mfaPolicy)
if err != nil {
log.Fatal(err)
}
_, err = client.PutBucketPolicy(context.TODO(), &s3.PutBucketPolicyInput{
Bucket: aws.String("my-bucket"),
Policy: aws.String(string(mfaPolicyJSON)),
})
if err != nil {
log.Fatal(err)
}
// Example 4: Bucket owner full control for cross-account access
crossAccountPolicy := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Sid": "DelegateS3Access",
"Effect": "Allow",
"Principal": map[string]string{
"AWS": "arn:aws:iam::123456789012:root",
},
"Action": []string{
"s3:ListBucket",
"s3:GetObject",
},
"Resource": []string{
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*",
},
},
},
}
crossAccountPolicyJSON, err := json.Marshal(crossAccountPolicy)
if err != nil {
log.Fatal(err)
}
_, err = client.PutBucketPolicy(context.TODO(), &s3.PutBucketPolicyInput{
Bucket: aws.String("my-bucket"),
Policy: aws.String(string(crossAccountPolicyJSON)),
})
if err != nil {
log.Fatal(err)
}
}Deletes the policy of a specified bucket.
func (c *Client) DeleteBucketPolicy(
ctx context.Context,
params *DeleteBucketPolicyInput,
optFns ...func(*Options),
) (*DeleteBucketPolicyOutput, error)type DeleteBucketPolicyInput struct {
// The bucket name.
// For directory buckets, use path-style requests.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Not supported for directory buckets.
// Required: No
ExpectedBucketOwner *string
}type DeleteBucketPolicyOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
_, err = client.DeleteBucketPolicy(context.TODO(), &s3.DeleteBucketPolicyInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
log.Println("Bucket policy deleted successfully")
}Retrieves the policy status for an Amazon S3 bucket, indicating whether the bucket is public.
Note: Not supported for directory buckets.
func (c *Client) GetBucketPolicyStatus(
ctx context.Context,
params *GetBucketPolicyStatusInput,
optFns ...func(*Options),
) (*GetBucketPolicyStatusOutput, error)type GetBucketPolicyStatusInput struct {
// The name of the Amazon S3 bucket whose policy status you want to retrieve.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type GetBucketPolicyStatusOutput struct {
// The policy status for the specified bucket.
PolicyStatus *types.PolicyStatus
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}PolicyStatus { .api }
type PolicyStatus struct {
// The policy status for this bucket. TRUE indicates that this bucket is public.
// FALSE indicates that the bucket is not public.
IsPublic *bool
}package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
output, err := client.GetBucketPolicyStatus(context.TODO(), &s3.GetBucketPolicyStatusInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
if output.PolicyStatus != nil && output.PolicyStatus.IsPublic != nil {
if *output.PolicyStatus.IsPublic {
fmt.Println("Bucket is PUBLIC")
} else {
fmt.Println("Bucket is NOT public")
}
}
}Returns the attribute-based access control (ABAC) property of the general purpose bucket.
Note: Only for general purpose buckets. Whether ABAC is enabled or disabled, you can use tags for cost tracking.
func (c *Client) GetBucketAbac(
ctx context.Context,
params *GetBucketAbacInput,
optFns ...func(*Options),
) (*GetBucketAbacOutput, error)type GetBucketAbacInput struct {
// The name of the general purpose bucket.
// Required: Yes
Bucket *string
// The Amazon Web Services account ID of the general purpose bucket's owner.
// Required: No
ExpectedBucketOwner *string
}type GetBucketAbacOutput struct {
// The ABAC status of the general purpose bucket.
AbacStatus *types.AbacStatus
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}AbacStatus { .api }
type AbacStatus struct {
// The ABAC status of the general purpose bucket.
// Values: Enabled | Disabled
Status types.BucketAbacStatus
}package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
output, err := client.GetBucketAbac(context.TODO(), &s3.GetBucketAbacInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
if output.AbacStatus != nil {
fmt.Printf("ABAC Status: %s\n", output.AbacStatus.Status)
}
}Sets the attribute-based access control (ABAC) property of the general purpose bucket.
Note: When ABAC is enabled, you must use TagResource, UntagResource, and ListTagsForResource actions to manage bucket tags. PutBucketTagging and DeleteBucketTagging are no longer available.
func (c *Client) PutBucketAbac(
ctx context.Context,
params *PutBucketAbacInput,
optFns ...func(*Options),
) (*PutBucketAbacOutput, error)type PutBucketAbacInput struct {
// The ABAC status of the general purpose bucket.
// Required: Yes
AbacStatus *types.AbacStatus
// The name of the general purpose bucket.
// Required: Yes
Bucket *string
// Indicates the algorithm to create the checksum.
// Values: CRC32 | CRC32C | SHA1 | SHA256
// Required: No
ChecksumAlgorithm types.ChecksumAlgorithm
// The MD5 hash of the PutBucketAbac request body.
// Required: No
ContentMD5 *string
// The Amazon Web Services account ID of the general purpose bucket's owner.
// Required: No
ExpectedBucketOwner *string
}type PutBucketAbacOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Enable ABAC for the bucket
_, err = client.PutBucketAbac(context.TODO(), &s3.PutBucketAbacInput{
Bucket: aws.String("my-bucket"),
AbacStatus: &types.AbacStatus{
Status: types.BucketAbacStatusEnabled,
},
})
if err != nil {
log.Fatal(err)
}
log.Println("ABAC enabled for bucket")
// Disable ABAC for the bucket
_, err = client.PutBucketAbac(context.TODO(), &s3.PutBucketAbacInput{
Bucket: aws.String("my-bucket"),
AbacStatus: &types.AbacStatus{
Status: types.BucketAbacStatusDisabled,
},
})
if err != nil {
log.Fatal(err)
}
log.Println("ABAC disabled for bucket")
}Retrieves the PublicAccessBlock configuration for an Amazon S3 bucket.
Note: Not supported for directory buckets. Amazon S3 evaluates the most restrictive combination of bucket-level and account-level settings.
func (c *Client) GetPublicAccessBlock(
ctx context.Context,
params *GetPublicAccessBlockInput,
optFns ...func(*Options),
) (*GetPublicAccessBlockOutput, error)type GetPublicAccessBlockInput struct {
// The name of the Amazon S3 bucket whose PublicAccessBlock configuration you
// want to retrieve.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type GetPublicAccessBlockOutput struct {
// The PublicAccessBlock configuration currently in effect for this Amazon S3 bucket.
PublicAccessBlockConfiguration *types.PublicAccessBlockConfiguration
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}PublicAccessBlockConfiguration { .api }
type PublicAccessBlockConfiguration struct {
// Specifies whether Amazon S3 should block public access control lists (ACLs)
// for this bucket and objects in this bucket.
// Setting to TRUE causes PUT Bucket ACL and PUT Object ACL calls with public
// ACLs to fail.
BlockPublicAcls *bool
// Specifies whether Amazon S3 should block public bucket policies for this bucket.
// Setting to TRUE causes Amazon S3 to reject calls to PUT Bucket policy if the
// specified bucket policy allows public access.
BlockPublicPolicy *bool
// Specifies whether Amazon S3 should ignore public ACLs for this bucket and
// objects in this bucket.
// Setting to TRUE causes Amazon S3 to ignore all public ACLs on this bucket
// and objects in this bucket.
IgnorePublicAcls *bool
// Specifies whether Amazon S3 should restrict public bucket policies for this bucket.
// Setting to TRUE restricts access to this bucket to only AWS service principals
// and authorized users within this account if the bucket has a public policy.
RestrictPublicBuckets *bool
}package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
output, err := client.GetPublicAccessBlock(context.TODO(), &s3.GetPublicAccessBlockInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
if output.PublicAccessBlockConfiguration != nil {
config := output.PublicAccessBlockConfiguration
fmt.Printf("BlockPublicAcls: %v\n", aws.ToBool(config.BlockPublicAcls))
fmt.Printf("BlockPublicPolicy: %v\n", aws.ToBool(config.BlockPublicPolicy))
fmt.Printf("IgnorePublicAcls: %v\n", aws.ToBool(config.IgnorePublicAcls))
fmt.Printf("RestrictPublicBuckets: %v\n", aws.ToBool(config.RestrictPublicBuckets))
}
}Creates or modifies the PublicAccessBlock configuration for an Amazon S3 bucket.
Note: Not supported for directory buckets.
func (c *Client) PutPublicAccessBlock(
ctx context.Context,
params *PutPublicAccessBlockInput,
optFns ...func(*Options),
) (*PutPublicAccessBlockOutput, error)type PutPublicAccessBlockInput struct {
// The name of the Amazon S3 bucket whose PublicAccessBlock configuration you
// want to set.
// Required: Yes
Bucket *string
// The PublicAccessBlock configuration to apply.
// Required: Yes
PublicAccessBlockConfiguration *types.PublicAccessBlockConfiguration
// Indicates the algorithm used to create the checksum.
// Values: CRC32 | CRC32C | SHA1 | SHA256
// Required: No
ChecksumAlgorithm types.ChecksumAlgorithm
// The MD5 hash of the PutPublicAccessBlock request body.
// Required: No
ContentMD5 *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type PutPublicAccessBlockOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Example 1: Block all public access
_, err = client.PutPublicAccessBlock(context.TODO(), &s3.PutPublicAccessBlockInput{
Bucket: aws.String("my-bucket"),
PublicAccessBlockConfiguration: &types.PublicAccessBlockConfiguration{
BlockPublicAcls: aws.Bool(true),
BlockPublicPolicy: aws.Bool(true),
IgnorePublicAcls: aws.Bool(true),
RestrictPublicBuckets: aws.Bool(true),
},
})
if err != nil {
log.Fatal(err)
}
log.Println("All public access blocked")
// Example 2: Block only public ACLs
_, err = client.PutPublicAccessBlock(context.TODO(), &s3.PutPublicAccessBlockInput{
Bucket: aws.String("my-bucket"),
PublicAccessBlockConfiguration: &types.PublicAccessBlockConfiguration{
BlockPublicAcls: aws.Bool(true),
BlockPublicPolicy: aws.Bool(false),
IgnorePublicAcls: aws.Bool(true),
RestrictPublicBuckets: aws.Bool(false),
},
})
if err != nil {
log.Fatal(err)
}
log.Println("Public ACLs blocked")
// Example 3: Allow public access (not recommended for production)
_, err = client.PutPublicAccessBlock(context.TODO(), &s3.PutPublicAccessBlockInput{
Bucket: aws.String("my-bucket"),
PublicAccessBlockConfiguration: &types.PublicAccessBlockConfiguration{
BlockPublicAcls: aws.Bool(false),
BlockPublicPolicy: aws.Bool(false),
IgnorePublicAcls: aws.Bool(false),
RestrictPublicBuckets: aws.Bool(false),
},
})
if err != nil {
log.Fatal(err)
}
log.Println("Public access allowed")
}Removes the PublicAccessBlock configuration for an Amazon S3 bucket.
Note: Not supported for directory buckets.
func (c *Client) DeletePublicAccessBlock(
ctx context.Context,
params *DeletePublicAccessBlockInput,
optFns ...func(*Options),
) (*DeletePublicAccessBlockOutput, error)type DeletePublicAccessBlockInput struct {
// The Amazon S3 bucket whose PublicAccessBlock configuration you want to delete.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type DeletePublicAccessBlockOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
_, err = client.DeletePublicAccessBlock(context.TODO(), &s3.DeletePublicAccessBlockInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
log.Println("Public access block configuration deleted")
}Retrieves OwnershipControls for an Amazon S3 bucket.
Note: Not supported for directory buckets. Buckets created before the BucketOwnerEnforced setting was introduced may not have OwnershipControls.
func (c *Client) GetBucketOwnershipControls(
ctx context.Context,
params *GetBucketOwnershipControlsInput,
optFns ...func(*Options),
) (*GetBucketOwnershipControlsOutput, error)type GetBucketOwnershipControlsInput struct {
// The name of the Amazon S3 bucket whose OwnershipControls you want to retrieve.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type GetBucketOwnershipControlsOutput struct {
// The OwnershipControls (BucketOwnerEnforced, BucketOwnerPreferred, or
// ObjectWriter) currently in effect for this Amazon S3 bucket.
OwnershipControls *types.OwnershipControls
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}OwnershipControls { .api }
type OwnershipControls struct {
// The container element for an ownership control rule.
// Required: Yes
Rules []OwnershipControlsRule
}OwnershipControlsRule { .api }
type OwnershipControlsRule struct {
// The container element for object ownership.
//
// Values:
// - BucketOwnerPreferred: Objects uploaded with bucket-owner-full-control
// canned ACL change ownership to the bucket owner.
// - ObjectWriter: The uploading account owns the object when uploaded with
// bucket-owner-full-control canned ACL.
// - BucketOwnerEnforced: ACLs are disabled. The bucket owner automatically
// owns and has full control over every object. The bucket only accepts
// PUT requests that don't specify an ACL or specify bucket owner full
// control ACLs.
//
// Required: Yes
ObjectOwnership types.ObjectOwnership
}package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
output, err := client.GetBucketOwnershipControls(context.TODO(), &s3.GetBucketOwnershipControlsInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
if output.OwnershipControls != nil {
for _, rule := range output.OwnershipControls.Rules {
fmt.Printf("Object Ownership: %s\n", rule.ObjectOwnership)
}
}
}Creates or modifies OwnershipControls for an Amazon S3 bucket.
Note: Not supported for directory buckets.
func (c *Client) PutBucketOwnershipControls(
ctx context.Context,
params *PutBucketOwnershipControlsInput,
optFns ...func(*Options),
) (*PutBucketOwnershipControlsOutput, error)type PutBucketOwnershipControlsInput struct {
// The name of the Amazon S3 bucket whose OwnershipControls you want to set.
// Required: Yes
Bucket *string
// The OwnershipControls to apply to this Amazon S3 bucket.
// Required: Yes
OwnershipControls *types.OwnershipControls
// Indicates the algorithm used to create the checksum.
// Values: CRC32 | CRC32C | SHA1 | SHA256
// Required: No
ChecksumAlgorithm types.ChecksumAlgorithm
// The MD5 hash of the OwnershipControls request body.
// Required: No
ContentMD5 *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type PutBucketOwnershipControlsOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Example 1: Set BucketOwnerEnforced (disables ACLs)
_, err = client.PutBucketOwnershipControls(context.TODO(), &s3.PutBucketOwnershipControlsInput{
Bucket: aws.String("my-bucket"),
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipBucketOwnerEnforced,
},
},
},
})
if err != nil {
log.Fatal(err)
}
log.Println("BucketOwnerEnforced ownership controls set (ACLs disabled)")
// Example 2: Set BucketOwnerPreferred
_, err = client.PutBucketOwnershipControls(context.TODO(), &s3.PutBucketOwnershipControlsInput{
Bucket: aws.String("my-bucket"),
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipBucketOwnerPreferred,
},
},
},
})
if err != nil {
log.Fatal(err)
}
log.Println("BucketOwnerPreferred ownership controls set")
// Example 3: Set ObjectWriter
_, err = client.PutBucketOwnershipControls(context.TODO(), &s3.PutBucketOwnershipControlsInput{
Bucket: aws.String("my-bucket"),
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipObjectWriter,
},
},
},
})
if err != nil {
log.Fatal(err)
}
log.Println("ObjectWriter ownership controls set")
}Removes OwnershipControls for an Amazon S3 bucket.
Note: Not supported for directory buckets.
func (c *Client) DeleteBucketOwnershipControls(
ctx context.Context,
params *DeleteBucketOwnershipControlsInput,
optFns ...func(*Options),
) (*DeleteBucketOwnershipControlsOutput, error)type DeleteBucketOwnershipControlsInput struct {
// The Amazon S3 bucket whose OwnershipControls you want to delete.
// Required: Yes
Bucket *string
// The account ID of the expected bucket owner.
// Required: No
ExpectedBucketOwner *string
}type DeleteBucketOwnershipControlsOutput struct {
// Metadata pertaining to the operation's result.
ResultMetadata middleware.Metadata
}package main
import (
"context"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
_, err = client.DeleteBucketOwnershipControls(context.TODO(), &s3.DeleteBucketOwnershipControlsInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
log.Fatal(err)
}
log.Println("Bucket ownership controls deleted")
}package main
import (
"context"
"encoding/json"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Complex policy with multiple conditions
complexPolicy := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Sid": "AllowCrossAccountReadWithIPRestriction",
"Effect": "Allow",
"Principal": map[string]string{
"AWS": "arn:aws:iam::123456789012:root",
},
"Action": []string{
"s3:GetObject",
"s3:ListBucket",
},
"Resource": []string{
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*",
},
"Condition": map[string]interface{}{
"IpAddress": map[string][]string{
"aws:SourceIp": {
"203.0.113.0/24",
"198.51.100.0/24",
},
},
"StringLike": map[string]string{
"s3:prefix": "public/*",
},
},
},
{
"Sid": "RequireSSLForUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": []string{
"arn:aws:s3:::my-bucket/*",
},
"Condition": map[string]interface{}{
"Bool": map[string]string{
"aws:SecureTransport": "false",
},
},
},
},
}
policyJSON, err := json.Marshal(complexPolicy)
if err != nil {
log.Fatal(err)
}
_, err = client.PutBucketPolicy(context.TODO(), &s3.PutBucketPolicyInput{
Bucket: aws.String("my-bucket"),
Policy: aws.String(string(policyJSON)),
})
if err != nil {
log.Fatal(err)
}
log.Println("Complex policy applied successfully")
}package main
import (
"context"
"encoding/json"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
// Tag-based access control policy
tagBasedPolicy := map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Sid": "AllowAccessBasedOnObjectTags",
"Effect": "Allow",
"Principal": map[string]string{
"AWS": "arn:aws:iam::123456789012:role/DevelopmentRole",
},
"Action": []string{
"s3:GetObject",
"s3:PutObject",
},
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": map[string]interface{}{
"StringEquals": map[string]string{
"s3:ExistingObjectTag/Environment": "Development",
},
},
},
{
"Sid": "AllowAccessBasedOnRequestTags",
"Effect": "Allow",
"Principal": map[string]string{
"AWS": "arn:aws:iam::123456789012:role/ProductionRole",
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": map[string]interface{}{
"StringEquals": map[string]string{
"s3:RequestObjectTag/Environment": "Production",
},
},
},
},
}
policyJSON, err := json.Marshal(tagBasedPolicy)
if err != nil {
log.Fatal(err)
}
_, err = client.PutBucketPolicy(context.TODO(), &s3.PutBucketPolicyInput{
Bucket: aws.String("my-bucket"),
Policy: aws.String(string(policyJSON)),
})
if err != nil {
log.Fatal(err)
}
log.Println("Tag-based policy applied successfully")
}Common errors when working with bucket access control operations:
package main
import (
"context"
"errors"
"log"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/aws-sdk-go-v2/aws"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatal(err)
}
client := s3.NewFromConfig(cfg)
_, err = client.GetBucketPolicy(context.TODO(), &s3.GetBucketPolicyInput{
Bucket: aws.String("my-bucket"),
})
if err != nil {
var noSuchBucket *types.NoSuchBucket
var noSuchConfig *types.NoSuchConfiguration
if errors.As(err, &noSuchBucket) {
log.Println("Bucket does not exist")
} else if errors.As(err, &noSuchConfig) {
log.Println("No bucket policy configured")
} else {
log.Fatal(err)
}
}
}Use Bucket Owner Enforced: For new buckets, set ObjectOwnership to BucketOwnerEnforced to disable ACLs and rely on bucket policies and IAM policies.
Block Public Access: Enable all public access block settings by default unless you specifically need public access.
Principle of Least Privilege: Grant only the minimum permissions required for users and applications.
Use Bucket Policies Over ACLs: Bucket policies provide more granular control and are easier to manage than ACLs.
Enable ABAC for Fine-Grained Control: Use ABAC with tags to implement attribute-based access control for more flexible permission management.
Use ExpectedBucketOwner: Always include the ExpectedBucketOwner parameter to prevent accidental operations on wrong buckets.
Require SSL/TLS: Include a policy statement that denies all requests not made over HTTPS.
Regular Audits: Use GetBucketPolicyStatus regularly to check if your buckets are public.
MFA Delete: For critical buckets, require MFA for delete operations using bucket policies.
Version Control Policies: Store bucket policies in version control and treat them as infrastructure as code.