To Nha Notes | May 19, 2023, 12:59 p.m.
I want to grant a user Amazon Simple Storage Service (Amazon S3) console access to a bucket or folder (prefix). However, I don't want the user to see other buckets in the account or other folders within the bucket.
Change a user's AWS Identity and Access Management (IAM) permissions to limit the user's Amazon S3 console access to a certain bucket or folder (prefix):
1. Remove permission to the s3:ListAllMyBuckets action.
2. Add permission to s3:ListBucket only for the bucket or folder that you want the user to access. To allow the user to upload and download objects from the bucket or folder, you must also include s3:PutObject and s3:GetObject.
1. Open the IAM console.
2. Select the IAM user or role that you want to restrict access to.
3. In the Permissions tab of the IAM user or role, expand each policy to view its JSON policy document.
4. In the JSON policy document, search for the policy that grants the user permission to the s3:ListAllMyBuckets action or to s3:* actions (all S3 actions).
5. Modify the policy to remove permission to the s3:ListAllMyBuckets action.
Note: If an attached user policy allows s3:* or Full Admin access with the "*" resource, then the policy includes the s3:ListAllMyBuckets permissions. Remove the "*" resource. Then, use one of the following example policies.
6. Add permission to s3:ListBucket only for the bucket or folder that you want the user to access from the console.
The following example policy is for access to an S3 bucket:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET" }, { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject" ], "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" } ] }
CDK code example
---- index.ts ------------
import { Construct } from 'constructs';
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as s3 from 'aws-cdk-lib/aws-s3';
interface CDIStackProps extends cdk.StackProps {
readonly isProd?: boolean;
readonly stage: string;
readonly project: string;
readonly vpc: ec2.IVpc;
readonly s3LogBucket: s3.IBucket;
}
export class CDIStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: CDIStackProps) {
super(scope, id, props);
const context = this.node.tryGetContext(props.stage).cdi;
// Create AWS IAM users group for client
const group = new iam.Group(this, '<GROUP_ID>', {
groupName: '<GROUP_NAME>',
});
// Create S3 bucket for all clients
const bucketName = '<BUCKET_NAME>';
const bucket = new s3.Bucket(this, `inboxBucket`, {
bucketName: bucketName,
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
enforceSSL: true,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: props?.isProd
? cdk.RemovalPolicy.RETAIN
: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: props?.isProd ? false : true,
serverAccessLogsBucket: props.s3LogBucket,
serverAccessLogsPrefix: `${bucketName}-logs/`,
lifecycleRules: [
{
enabled: true,
abortIncompleteMultipartUploadAfter: cdk.Duration.days(30),
expiredObjectDeleteMarker: true,
transitions: [
{
storageClass: s3.StorageClass.INFREQUENT_ACCESS,
transitionAfter: cdk.Duration.days(90),
},
],
},
],
});
context.clients.forEach((client: string) => {
// Create AWS IAM user for client
const userName = `${client}-user`;
const user = new iam.User(this, `user${client}`, {
userName: userName,
groups: [group],
});
// create the access key and secret access key combination for created user
const accessKey = new iam.CfnAccessKey(this, `userAccessKey${client}`, {
userName: user.userName
});
const uid = cdk.Names.uniqueId(user);
const hashId = uid.substring(uid.length - 7, uid.length).toLowerCase();
const bucketFolder = `${client}-inbox-${hashId}`;
bucket.addToResourcePolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
principals: [new iam.ArnPrincipal(user.userArn)],
actions: ['s3:PutObject'],
resources: [
`${bucket.bucketArn}/${bucketFolder}/*`
],
}),
);
// Note: enable below lines of code to print secured outputs, save them to 1password and share to clients later.
// new cdk.CfnOutput(this, `${client}User`, { value: userName });
// new cdk.CfnOutput(this, `${client}AccessKeyId`, { value: accessKey.ref });
// new cdk.CfnOutput(this, `${client}SecretAccessKey`, { value: accessKey.attrSecretAccessKey });
// new cdk.CfnOutput(this, `${client}BucketURI`, { value: `s3://${bucketName}/${bucketFolder}` });
});
}
}
https://repost.aws/knowledge-center/s3-console-access-certain-bucket