Upload Files to AWS S3 Buckets

The aws:s3/bucketObject:BucketObject resource, part of the Pulumi AWS provider, uploads and manages individual objects within S3 buckets: their content, encryption, and retention policies. This guide focuses on three capabilities: file upload with change detection, encryption options, and Object Lock for compliance.

Objects require an existing S3 bucket and may reference KMS keys for encryption. The examples are intentionally small. Combine them with your own bucket configuration, access policies, and lifecycle rules.

Upload a file with content change detection

Most deployments start by uploading a local file and tracking when it needs re-uploading.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";

const object = new aws.s3.BucketObject("object", {
    bucket: "your_bucket_name",
    key: "new_object_key",
    source: new pulumi.asset.FileAsset("path/to/file"),
    etag: std.filemd5({
        input: "path/to/file",
    }).then(invoke => invoke.result),
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std

object = aws.s3.BucketObject("object",
    bucket="your_bucket_name",
    key="new_object_key",
    source=pulumi.FileAsset("path/to/file"),
    etag=std.filemd5(input="path/to/file").result)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		invokeFilemd5, err := std.Filemd5(ctx, &std.Filemd5Args{
			Input: "path/to/file",
		}, nil)
		if err != nil {
			return err
		}
		_, err = s3.NewBucketObject(ctx, "object", &s3.BucketObjectArgs{
			Bucket: pulumi.Any("your_bucket_name"),
			Key:    pulumi.String("new_object_key"),
			Source: pulumi.NewFileAsset("path/to/file"),
			Etag:   pulumi.String(invokeFilemd5.Result),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var @object = new Aws.S3.BucketObject("object", new()
    {
        Bucket = "your_bucket_name",
        Key = "new_object_key",
        Source = new FileAsset("path/to/file"),
        Etag = Std.Filemd5.Invoke(new()
        {
            Input = "path/to/file",
        }).Apply(invoke => invoke.Result),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.BucketObject;
import com.pulumi.aws.s3.BucketObjectArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.Filemd5Args;
import com.pulumi.asset.FileAsset;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var object = new BucketObject("object", BucketObjectArgs.builder()
            .bucket("your_bucket_name")
            .key("new_object_key")
            .source(new FileAsset("path/to/file"))
            .etag(StdFunctions.filemd5(Filemd5Args.builder()
                .input("path/to/file")
                .build()).result())
            .build());

    }
}
resources:
  object:
    type: aws:s3:BucketObject
    properties:
      bucket: your_bucket_name
      key: new_object_key
      source:
        fn::FileAsset: path/to/file
      etag:
        fn::invoke:
          function: std:filemd5
          arguments:
            input: path/to/file
          return: result

The source property points to your local file path. The etag property uses filemd5 to compute a hash of the file content; when the file changes, Pulumi detects the new hash and re-uploads the object. The key property sets the object’s name in the bucket.

Encrypt objects with a customer-managed KMS key

Applications with strict encryption requirements use customer-managed KMS keys to control rotation and access.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const examplekms = new aws.kms.Key("examplekms", {
    description: "KMS key 1",
    deletionWindowInDays: 7,
});
const examplebucket = new aws.s3.Bucket("examplebucket", {bucket: "examplebuckettftest"});
const example = new aws.s3.BucketAcl("example", {
    bucket: examplebucket.id,
    acl: "private",
});
const exampleBucketObject = new aws.s3.BucketObject("example", {
    key: "someobject",
    bucket: examplebucket.id,
    source: new pulumi.asset.FileAsset("index.html"),
    kmsKeyId: examplekms.arn,
});
import pulumi
import pulumi_aws as aws

examplekms = aws.kms.Key("examplekms",
    description="KMS key 1",
    deletion_window_in_days=7)
examplebucket = aws.s3.Bucket("examplebucket", bucket="examplebuckettftest")
example = aws.s3.BucketAcl("example",
    bucket=examplebucket.id,
    acl="private")
example_bucket_object = aws.s3.BucketObject("example",
    key="someobject",
    bucket=examplebucket.id,
    source=pulumi.FileAsset("index.html"),
    kms_key_id=examplekms.arn)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		examplekms, err := kms.NewKey(ctx, "examplekms", &kms.KeyArgs{
			Description:          pulumi.String("KMS key 1"),
			DeletionWindowInDays: pulumi.Int(7),
		})
		if err != nil {
			return err
		}
		examplebucket, err := s3.NewBucket(ctx, "examplebucket", &s3.BucketArgs{
			Bucket: pulumi.String("examplebuckettftest"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketAcl(ctx, "example", &s3.BucketAclArgs{
			Bucket: examplebucket.ID(),
			Acl:    pulumi.String("private"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketObject(ctx, "example", &s3.BucketObjectArgs{
			Key:      pulumi.String("someobject"),
			Bucket:   examplebucket.ID(),
			Source:   pulumi.NewFileAsset("index.html"),
			KmsKeyId: examplekms.Arn,
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var examplekms = new Aws.Kms.Key("examplekms", new()
    {
        Description = "KMS key 1",
        DeletionWindowInDays = 7,
    });

    var examplebucket = new Aws.S3.Bucket("examplebucket", new()
    {
        BucketName = "examplebuckettftest",
    });

    var example = new Aws.S3.BucketAcl("example", new()
    {
        Bucket = examplebucket.Id,
        Acl = "private",
    });

    var exampleBucketObject = new Aws.S3.BucketObject("example", new()
    {
        Key = "someobject",
        Bucket = examplebucket.Id,
        Source = new FileAsset("index.html"),
        KmsKeyId = examplekms.Arn,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.s3.Bucket;
import com.pulumi.aws.s3.BucketArgs;
import com.pulumi.aws.s3.BucketAcl;
import com.pulumi.aws.s3.BucketAclArgs;
import com.pulumi.aws.s3.BucketObject;
import com.pulumi.aws.s3.BucketObjectArgs;
import com.pulumi.asset.FileAsset;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var examplekms = new Key("examplekms", KeyArgs.builder()
            .description("KMS key 1")
            .deletionWindowInDays(7)
            .build());

        var examplebucket = new Bucket("examplebucket", BucketArgs.builder()
            .bucket("examplebuckettftest")
            .build());

        var example = new BucketAcl("example", BucketAclArgs.builder()
            .bucket(examplebucket.id())
            .acl("private")
            .build());

        var exampleBucketObject = new BucketObject("exampleBucketObject", BucketObjectArgs.builder()
            .key("someobject")
            .bucket(examplebucket.id())
            .source(new FileAsset("index.html"))
            .kmsKeyId(examplekms.arn())
            .build());

    }
}
resources:
  examplekms:
    type: aws:kms:Key
    properties:
      description: KMS key 1
      deletionWindowInDays: 7
  examplebucket:
    type: aws:s3:Bucket
    properties:
      bucket: examplebuckettftest
  example:
    type: aws:s3:BucketAcl
    properties:
      bucket: ${examplebucket.id}
      acl: private
  exampleBucketObject:
    type: aws:s3:BucketObject
    name: example
    properties:
      key: someobject
      bucket: ${examplebucket.id}
      source:
        fn::FileAsset: index.html
      kmsKeyId: ${examplekms.arn}

The kmsKeyId property references a KMS key ARN for encryption. When you upload the object, S3 encrypts it using the specified key. This gives you control over key policies, rotation schedules, and audit trails through CloudTrail.

Encrypt objects with AWS-managed encryption

For simpler encryption needs, S3 provides AWS-managed keys that require no provisioning.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const examplebucket = new aws.s3.Bucket("examplebucket", {bucket: "examplebuckettftest"});
const example = new aws.s3.BucketAcl("example", {
    bucket: examplebucket.id,
    acl: "private",
});
const exampleBucketObject = new aws.s3.BucketObject("example", {
    key: "someobject",
    bucket: examplebucket.id,
    source: new pulumi.asset.FileAsset("index.html"),
    serverSideEncryption: "AES256",
});
import pulumi
import pulumi_aws as aws

examplebucket = aws.s3.Bucket("examplebucket", bucket="examplebuckettftest")
example = aws.s3.BucketAcl("example",
    bucket=examplebucket.id,
    acl="private")
example_bucket_object = aws.s3.BucketObject("example",
    key="someobject",
    bucket=examplebucket.id,
    source=pulumi.FileAsset("index.html"),
    server_side_encryption="AES256")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		examplebucket, err := s3.NewBucket(ctx, "examplebucket", &s3.BucketArgs{
			Bucket: pulumi.String("examplebuckettftest"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketAcl(ctx, "example", &s3.BucketAclArgs{
			Bucket: examplebucket.ID(),
			Acl:    pulumi.String("private"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketObject(ctx, "example", &s3.BucketObjectArgs{
			Key:                  pulumi.String("someobject"),
			Bucket:               examplebucket.ID(),
			Source:               pulumi.NewFileAsset("index.html"),
			ServerSideEncryption: pulumi.String("AES256"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var examplebucket = new Aws.S3.Bucket("examplebucket", new()
    {
        BucketName = "examplebuckettftest",
    });

    var example = new Aws.S3.BucketAcl("example", new()
    {
        Bucket = examplebucket.Id,
        Acl = "private",
    });

    var exampleBucketObject = new Aws.S3.BucketObject("example", new()
    {
        Key = "someobject",
        Bucket = examplebucket.Id,
        Source = new FileAsset("index.html"),
        ServerSideEncryption = "AES256",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.Bucket;
import com.pulumi.aws.s3.BucketArgs;
import com.pulumi.aws.s3.BucketAcl;
import com.pulumi.aws.s3.BucketAclArgs;
import com.pulumi.aws.s3.BucketObject;
import com.pulumi.aws.s3.BucketObjectArgs;
import com.pulumi.asset.FileAsset;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var examplebucket = new Bucket("examplebucket", BucketArgs.builder()
            .bucket("examplebuckettftest")
            .build());

        var example = new BucketAcl("example", BucketAclArgs.builder()
            .bucket(examplebucket.id())
            .acl("private")
            .build());

        var exampleBucketObject = new BucketObject("exampleBucketObject", BucketObjectArgs.builder()
            .key("someobject")
            .bucket(examplebucket.id())
            .source(new FileAsset("index.html"))
            .serverSideEncryption("AES256")
            .build());

    }
}
resources:
  examplebucket:
    type: aws:s3:Bucket
    properties:
      bucket: examplebuckettftest
  example:
    type: aws:s3:BucketAcl
    properties:
      bucket: ${examplebucket.id}
      acl: private
  exampleBucketObject:
    type: aws:s3:BucketObject
    name: example
    properties:
      key: someobject
      bucket: ${examplebucket.id}
      source:
        fn::FileAsset: index.html
      serverSideEncryption: AES256

The serverSideEncryption property set to “AES256” enables encryption with AWS-managed keys. S3 handles key management automatically; you don’t provision or rotate keys yourself. This provides encryption at rest without the overhead of managing KMS resources.

Apply retention policies with Object Lock

Compliance workloads require immutable storage where objects cannot be deleted or modified for a period.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const examplebucket = new aws.s3.Bucket("examplebucket", {
    bucket: "examplebuckettftest",
    objectLockEnabled: true,
});
const example = new aws.s3.BucketAcl("example", {
    bucket: examplebucket.id,
    acl: "private",
});
const exampleBucketVersioning = new aws.s3.BucketVersioning("example", {
    bucket: examplebucket.id,
    versioningConfiguration: {
        status: "Enabled",
    },
});
const exampleBucketObject = new aws.s3.BucketObject("example", {
    key: "someobject",
    bucket: examplebucket.id,
    source: new pulumi.asset.FileAsset("important.txt"),
    objectLockLegalHoldStatus: "ON",
    objectLockMode: "GOVERNANCE",
    objectLockRetainUntilDate: "2021-12-31T23:59:60Z",
    forceDestroy: true,
}, {
    dependsOn: [exampleBucketVersioning],
});
import pulumi
import pulumi_aws as aws

examplebucket = aws.s3.Bucket("examplebucket",
    bucket="examplebuckettftest",
    object_lock_enabled=True)
example = aws.s3.BucketAcl("example",
    bucket=examplebucket.id,
    acl="private")
example_bucket_versioning = aws.s3.BucketVersioning("example",
    bucket=examplebucket.id,
    versioning_configuration={
        "status": "Enabled",
    })
example_bucket_object = aws.s3.BucketObject("example",
    key="someobject",
    bucket=examplebucket.id,
    source=pulumi.FileAsset("important.txt"),
    object_lock_legal_hold_status="ON",
    object_lock_mode="GOVERNANCE",
    object_lock_retain_until_date="2021-12-31T23:59:60Z",
    force_destroy=True,
    opts = pulumi.ResourceOptions(depends_on=[example_bucket_versioning]))
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		examplebucket, err := s3.NewBucket(ctx, "examplebucket", &s3.BucketArgs{
			Bucket:            pulumi.String("examplebuckettftest"),
			ObjectLockEnabled: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketAcl(ctx, "example", &s3.BucketAclArgs{
			Bucket: examplebucket.ID(),
			Acl:    pulumi.String("private"),
		})
		if err != nil {
			return err
		}
		exampleBucketVersioning, err := s3.NewBucketVersioning(ctx, "example", &s3.BucketVersioningArgs{
			Bucket: examplebucket.ID(),
			VersioningConfiguration: &s3.BucketVersioningVersioningConfigurationArgs{
				Status: pulumi.String("Enabled"),
			},
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketObject(ctx, "example", &s3.BucketObjectArgs{
			Key:                       pulumi.String("someobject"),
			Bucket:                    examplebucket.ID(),
			Source:                    pulumi.NewFileAsset("important.txt"),
			ObjectLockLegalHoldStatus: pulumi.String("ON"),
			ObjectLockMode:            pulumi.String("GOVERNANCE"),
			ObjectLockRetainUntilDate: pulumi.String("2021-12-31T23:59:60Z"),
			ForceDestroy:              pulumi.Bool(true),
		}, pulumi.DependsOn([]pulumi.Resource{
			exampleBucketVersioning,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var examplebucket = new Aws.S3.Bucket("examplebucket", new()
    {
        BucketName = "examplebuckettftest",
        ObjectLockEnabled = true,
    });

    var example = new Aws.S3.BucketAcl("example", new()
    {
        Bucket = examplebucket.Id,
        Acl = "private",
    });

    var exampleBucketVersioning = new Aws.S3.BucketVersioning("example", new()
    {
        Bucket = examplebucket.Id,
        VersioningConfiguration = new Aws.S3.Inputs.BucketVersioningVersioningConfigurationArgs
        {
            Status = "Enabled",
        },
    });

    var exampleBucketObject = new Aws.S3.BucketObject("example", new()
    {
        Key = "someobject",
        Bucket = examplebucket.Id,
        Source = new FileAsset("important.txt"),
        ObjectLockLegalHoldStatus = "ON",
        ObjectLockMode = "GOVERNANCE",
        ObjectLockRetainUntilDate = "2021-12-31T23:59:60Z",
        ForceDestroy = true,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            exampleBucketVersioning,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.Bucket;
import com.pulumi.aws.s3.BucketArgs;
import com.pulumi.aws.s3.BucketAcl;
import com.pulumi.aws.s3.BucketAclArgs;
import com.pulumi.aws.s3.BucketVersioning;
import com.pulumi.aws.s3.BucketVersioningArgs;
import com.pulumi.aws.s3.inputs.BucketVersioningVersioningConfigurationArgs;
import com.pulumi.aws.s3.BucketObject;
import com.pulumi.aws.s3.BucketObjectArgs;
import com.pulumi.asset.FileAsset;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var examplebucket = new Bucket("examplebucket", BucketArgs.builder()
            .bucket("examplebuckettftest")
            .objectLockEnabled(true)
            .build());

        var example = new BucketAcl("example", BucketAclArgs.builder()
            .bucket(examplebucket.id())
            .acl("private")
            .build());

        var exampleBucketVersioning = new BucketVersioning("exampleBucketVersioning", BucketVersioningArgs.builder()
            .bucket(examplebucket.id())
            .versioningConfiguration(BucketVersioningVersioningConfigurationArgs.builder()
                .status("Enabled")
                .build())
            .build());

        var exampleBucketObject = new BucketObject("exampleBucketObject", BucketObjectArgs.builder()
            .key("someobject")
            .bucket(examplebucket.id())
            .source(new FileAsset("important.txt"))
            .objectLockLegalHoldStatus("ON")
            .objectLockMode("GOVERNANCE")
            .objectLockRetainUntilDate("2021-12-31T23:59:60Z")
            .forceDestroy(true)
            .build(), CustomResourceOptions.builder()
                .dependsOn(exampleBucketVersioning)
                .build());

    }
}
resources:
  examplebucket:
    type: aws:s3:Bucket
    properties:
      bucket: examplebuckettftest
      objectLockEnabled: true
  example:
    type: aws:s3:BucketAcl
    properties:
      bucket: ${examplebucket.id}
      acl: private
  exampleBucketVersioning:
    type: aws:s3:BucketVersioning
    name: example
    properties:
      bucket: ${examplebucket.id}
      versioningConfiguration:
        status: Enabled
  exampleBucketObject:
    type: aws:s3:BucketObject
    name: example
    properties:
      key: someobject
      bucket: ${examplebucket.id}
      source:
        fn::FileAsset: important.txt
      objectLockLegalHoldStatus: ON
      objectLockMode: GOVERNANCE
      objectLockRetainUntilDate: 2021-12-31T23:59:60Z
      forceDestroy: true
    options:
      dependsOn:
        - ${exampleBucketVersioning}

Object Lock prevents deletion or modification until the retention period expires. The objectLockMode property sets the retention type (GOVERNANCE allows privileged users to override; COMPLIANCE is immutable). The objectLockRetainUntilDate property specifies when the lock expires. The forceDestroy property must be true to allow Pulumi to remove the object during stack deletion. Object Lock requires versioning enabled on the bucket and objectLockEnabled set at bucket creation time.

Beyond these examples

These snippets focus on specific object-level features: file upload with change detection, encryption (KMS and AWS-managed keys), and Object Lock for compliance. They’re intentionally minimal rather than full storage solutions.

The examples reference pre-existing infrastructure such as S3 buckets (which must exist before creating objects) and KMS keys for customer-managed encryption. They focus on object configuration rather than provisioning buckets or access policies.

To keep things focused, common object patterns are omitted, including:

  • Storage class selection (STANDARD, GLACIER, etc.)
  • Content metadata (contentType, cacheControl, contentDisposition)
  • Access control (ACLs and tags)
  • Website redirects and content encoding

These omissions are intentional: the goal is to illustrate how each object feature is wired, not provide drop-in storage modules. See the S3 BucketObject resource reference for all available configuration options.

Let's upload Files to AWS S3 Buckets

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Content & Upload
What are the different ways to provide content for an S3 object?
You have three options: source (path to a local file), content (literal string uploaded as UTF-8), or contentBase64 (base64-encoded binary data). If none are provided, the object will be empty.
How do I upload a file to S3?
Use the source property with a FileAsset pointing to your local file path, as shown in the basic upload example.
When should I use contentBase64 instead of source?
Use contentBase64 only for small content like the result of gzipbase64 with small text strings. For larger objects, use source to stream content from a disk file.
What happens if I specify contentEncoding?
You’re responsible for encoding the body appropriately. The source, content, and contentBase64 properties all expect already encoded/compressed bytes.
Encryption & Security
How do I trigger updates when using KMS encryption?
Use sourceHash instead of etag. The etag attribute is incompatible with KMS encryption (kmsKeyId or serverSideEncryption = "aws:kms").
What encryption options are available for S3 objects?
You can use serverSideEncryption with “AES256” (AWS-managed key) or “aws:kms” (S3 default master key). For custom KMS keys, set kmsKeyId to your KMS key ARN.
What KMS key attribute should I reference?
Use the arn attribute when referencing aws.kms.Key resource, or targetKeyArn when referencing aws.kms.Alias.
Object Lock & Deletion
How do I configure S3 Object Lock?
Enable object lock on the bucket, enable versioning, then set objectLockLegalHoldStatus (ON/OFF), objectLockMode (GOVERNANCE/COMPLIANCE), and objectLockRetainUntilDate (RFC3339 format). Use dependsOn to ensure versioning is enabled first.
When should I set forceDestroy to true?
Set forceDestroy: true only if the bucket has S3 object lock enabled. This allows deletion of objects by removing any legal hold on object versions.
Configuration & Immutability
What properties are immutable after creation?
The bucket and key properties are immutable. Changing either will force resource replacement.
What's the default storage class for S3 objects?
Objects default to “STANDARD” storage class unless you specify a different value in storageClass.
Why are my metadata keys not working?
Metadata keys must be lowercase. Only lowercase labels are currently supported by the AWS Go API.

Using a different cloud?

Explore storage guides for other cloud providers: