Configure AWS S3 Access Points

The aws:s3/accessPoint:AccessPoint resource, part of the Pulumi AWS provider, creates named network endpoints for S3 buckets that simplify permission management and network access control. This guide focuses on two capabilities: creating access points for general purpose buckets and restricting access to VPC traffic.

Access points attach to existing S3 buckets and may reference VPC infrastructure for network restrictions. The examples are intentionally small. Combine them with your own bucket policies and network configuration.

Create an access point for a general purpose bucket

Most deployments start with a standard general purpose bucket in an AWS region. Access points provide named endpoints that simplify permission management for shared buckets.

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

const example = new aws.s3.Bucket("example", {bucket: "example"});
const exampleAccessPoint = new aws.s3.AccessPoint("example", {
    bucket: example.id,
    name: "example",
});
import pulumi
import pulumi_aws as aws

example = aws.s3.Bucket("example", bucket="example")
example_access_point = aws.s3.AccessPoint("example",
    bucket=example.id,
    name="example")
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 {
		example, err := s3.NewBucket(ctx, "example", &s3.BucketArgs{
			Bucket: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewAccessPoint(ctx, "example", &s3.AccessPointArgs{
			Bucket: example.ID(),
			Name:   pulumi.String("example"),
		})
		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 example = new Aws.S3.Bucket("example", new()
    {
        BucketName = "example",
    });

    var exampleAccessPoint = new Aws.S3.AccessPoint("example", new()
    {
        Bucket = example.Id,
        Name = "example",
    });

});
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.AccessPoint;
import com.pulumi.aws.s3.AccessPointArgs;
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 example = new Bucket("example", BucketArgs.builder()
            .bucket("example")
            .build());

        var exampleAccessPoint = new AccessPoint("exampleAccessPoint", AccessPointArgs.builder()
            .bucket(example.id())
            .name("example")
            .build());

    }
}
resources:
  example:
    type: aws:s3:Bucket
    properties:
      bucket: example
  exampleAccessPoint:
    type: aws:s3:AccessPoint
    name: example
    properties:
      bucket: ${example.id}
      name: example

The bucket property references an existing S3 bucket by ID. The name property assigns a unique identifier to the access point. Without additional configuration, the access point inherits the bucket’s permissions and allows internet access subject to bucket policies.

Restrict access to requests from a VPC

Applications in private subnets often need S3 access without traversing the public internet. VPC-restricted access points keep traffic within your network boundary.

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

const example = new aws.s3control.Bucket("example", {bucket: "example"});
const exampleVpc = new aws.ec2.Vpc("example", {cidrBlock: "10.0.0.0/16"});
const exampleAccessPoint = new aws.s3.AccessPoint("example", {
    bucket: example.arn,
    name: "example",
    vpcConfiguration: {
        vpcId: exampleVpc.id,
    },
});
import pulumi
import pulumi_aws as aws

example = aws.s3control.Bucket("example", bucket="example")
example_vpc = aws.ec2.Vpc("example", cidr_block="10.0.0.0/16")
example_access_point = aws.s3.AccessPoint("example",
    bucket=example.arn,
    name="example",
    vpc_configuration={
        "vpc_id": example_vpc.id,
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := s3control.NewBucket(ctx, "example", &s3control.BucketArgs{
			Bucket: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		exampleVpc, err := ec2.NewVpc(ctx, "example", &ec2.VpcArgs{
			CidrBlock: pulumi.String("10.0.0.0/16"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewAccessPoint(ctx, "example", &s3.AccessPointArgs{
			Bucket: example.Arn,
			Name:   pulumi.String("example"),
			VpcConfiguration: &s3.AccessPointVpcConfigurationArgs{
				VpcId: exampleVpc.ID(),
			},
		})
		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 example = new Aws.S3Control.Bucket("example", new()
    {
        BucketName = "example",
    });

    var exampleVpc = new Aws.Ec2.Vpc("example", new()
    {
        CidrBlock = "10.0.0.0/16",
    });

    var exampleAccessPoint = new Aws.S3.AccessPoint("example", new()
    {
        Bucket = example.Arn,
        Name = "example",
        VpcConfiguration = new Aws.S3.Inputs.AccessPointVpcConfigurationArgs
        {
            VpcId = exampleVpc.Id,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3control.Bucket;
import com.pulumi.aws.s3control.BucketArgs;
import com.pulumi.aws.ec2.Vpc;
import com.pulumi.aws.ec2.VpcArgs;
import com.pulumi.aws.s3.AccessPoint;
import com.pulumi.aws.s3.AccessPointArgs;
import com.pulumi.aws.s3.inputs.AccessPointVpcConfigurationArgs;
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 example = new Bucket("example", BucketArgs.builder()
            .bucket("example")
            .build());

        var exampleVpc = new Vpc("exampleVpc", VpcArgs.builder()
            .cidrBlock("10.0.0.0/16")
            .build());

        var exampleAccessPoint = new AccessPoint("exampleAccessPoint", AccessPointArgs.builder()
            .bucket(example.arn())
            .name("example")
            .vpcConfiguration(AccessPointVpcConfigurationArgs.builder()
                .vpcId(exampleVpc.id())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:s3control:Bucket
    properties:
      bucket: example
  exampleAccessPoint:
    type: aws:s3:AccessPoint
    name: example
    properties:
      bucket: ${example.arn}
      name: example
      vpcConfiguration:
        vpcId: ${exampleVpc.id}
  exampleVpc:
    type: aws:ec2:Vpc
    name: example
    properties:
      cidrBlock: 10.0.0.0/16

The vpcConfiguration property limits access to requests originating from the specified VPC. When configured, the networkOrigin output shows “VPC” instead of “Internet”, and the access point rejects requests from outside the VPC. This configuration is required for S3 on Outposts buckets.

Beyond these examples

These snippets focus on specific access point features: access point creation for general purpose and Outposts buckets, and VPC-restricted network access. They’re intentionally minimal rather than full access control solutions.

The examples reference pre-existing infrastructure such as S3 buckets (general purpose or Outposts) and VPC infrastructure for VPC-restricted access points. They focus on configuring the access point rather than provisioning buckets or network infrastructure.

To keep things focused, common access point patterns are omitted, including:

  • Access point policies (policy property or standalone AccessPointPolicy resource)
  • Public access block configuration (publicAccessBlockConfiguration)
  • Directory bucket access points (shown but not explained in detail)

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

Let's configure AWS S3 Access Points

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Policy Management
Why is my access point policy being overwritten?
You can’t use an inline policy on the access point resource alongside the standalone aws.s3control.AccessPointPolicy resource. Using both causes policy conflicts and overwrites. Choose one approach or the other.
How do I remove a policy from my access point?
Setting policy to null or an empty string won’t delete the policy (it may have been set by aws.s3control.AccessPointPolicy). To remove it, set policy to "{}" (an empty JSON document).
Configuration & Immutability
What properties can't I change after creating an access point?
The following properties are immutable: accountId, bucket, bucketAccountId, name, publicAccessBlockConfiguration, and vpcConfiguration. Changing any of these requires recreating the access point.
How do I create access points for different bucket types?

You have three options:

  1. General Purpose Bucket - Use the bucket name in the bucket property
  2. S3 on Outposts - Use the bucket ARN and include vpcConfiguration (required)
  3. Directory Bucket - Use special naming format with zoneId (e.g., example--zoneId--x-s3)
What defaults to the provider configuration?
Both accountId and region default to the values set in your AWS provider configuration if not explicitly specified.
Connectivity & Endpoints
Why can't I access my access point over HTTP?
S3 access points only support HTTPS. HTTP requests will fail. Always use HTTPS URLs when accessing the domainName.
Which endpoint should I use for custom API configurations?
Use the s3control endpoint provider configuration, not the s3 endpoint. This resource is managed through the S3 Control API.
What does the networkOrigin property indicate?
networkOrigin shows whether the access point allows public Internet access (Internet) or only VPC access (VPC). This is determined by your vpcConfiguration settings.
Import & Migration
How do I import existing access points?
For General Purpose buckets, use account_id:name format. For S3 on Outposts, use the full ARN. Example: pulumi import aws:s3/accessPoint:AccessPoint example 123456789012:example

Using a different cloud?

Explore storage guides for other cloud providers: