Bucket
A private S3 bucket with encryption, TLS-only access and production versioning on by default. Grant access in one line instead of writing IAM policy.
Minimal
The smallest config that deploys.
import { App } from '@anvil-cloud/sdk';
import * as anvil from '@anvil-cloud/sdk';
export default new App({
run(ctx) {
const uploads = new anvil.aws.Bucket('uploads');
},
});import anvil_cloud as anvil
def infra(ctx: anvil.Context):
uploads = anvil.aws.Bucket("uploads")
anvil.App(run=infra)package main
import (
"github.com/anvil-cloud/anvil/sdk/go/anvil"
anvilaws "github.com/anvil-cloud/anvil/sdk/go/anvil/aws"
)
func main() {
anvil.Run(anvil.AppConfig{
Run: func(ctx *anvil.Context) error {
_, err := anvilaws.NewBucket(ctx.PulumiCtx(), "uploads", nil)
if err != nil {
return err
}
return nil
},
})
}Granting access
Grant compute access with one method per kind of access: grantRead, grantWrite, grantReadWrite, grantDelete or grantFullAccess. Pass key prefixes to limit it to part of the bucket.
uploads.grantRead(api); // the whole bucket
uploads.grantReadWrite(worker, ['inbox/*']); // only keys under inbox/uploads.grant_read(api) # the whole bucket
uploads.grant_read_write(worker, paths=["inbox/*"]) # only keys under inbox/// Go has no grant methods yet: give the Lambda the same actions with permissions.
worker, err := anvilaws.NewLambda(ctx.PulumiCtx(), "worker", &anvilaws.LambdaArgs{
Runtime: anvilaws.LambdaRuntime_Nodejs24_x,
Handler: pulumi.String("functions/worker/index.handler"),
Permissions: anvilaws.LambdaPermissionArray{
// grantReadWrite(worker, ['inbox/*']): objects under inbox/ only.
anvilaws.LambdaPermissionArgs{
Actions: pulumi.ToStringArray([]string{"s3:GetObject", "s3:PutObject"}),
Resource: uploads.Arn,
Path: pulumi.String("inbox"),
},
anvilaws.LambdaPermissionArgs{
Actions: pulumi.ToStringArray([]string{"s3:ListBucket"}),
Resource: uploads.Arn,
},
},
})
if err != nil {
return err
}What Anvil creates
grantReadaddss3:GetObjectands3:ListBucket,grantWriteaddss3:PutObjectandgrantDeleteaddss3:DeleteObject.grantReadWriteis read plus write, andgrantFullAccessis all four. No grant can change the bucket's policy or settings.- The actions apply to this bucket only. With prefixes, object reads, writes and deletes apply only to keys under them.
s3:ListBucketisn't limited by prefix, so compute that can read part of the bucket can still list every key name in it.- Each grant is an inline policy on the compute's role, removed when you remove the grant.
Good to know
- Public access is blocked, objects are encrypted with SSE-S3 and only TLS requests are allowed, with nothing to configure.
- Versioning is always on in production stages. Set
versioningto turn it on elsewhere, andversionRetentionso old versions don't pile up. - Without
storageTransition, objects use Intelligent-Tiering. retention(Object Lock) can only be set when the bucket is created, and locked objects can't be deleted or overwritten until their period ends.
The Full example tab has a complete programand the runtime code that uses it. Every argument and attribute is on the Reference tab.