@cloud-copilot/iam-collect
Version:
Collect IAM information from AWS Accounts
113 lines • 4.41 kB
JavaScript
import { GetBucketEncryptionCommand, GetBucketPolicyCommand, GetBucketTaggingCommand, GetPublicAccessBlockCommand, ListBucketsCommand, S3Client } from '@aws-sdk/client-s3';
import { AwsClientPool } from '../../aws/ClientPool.js';
import { runAndCatch404 } from '../../utils/client-tools.js';
import { syncData } from '../sync.js';
import { paginateResource } from '../typedSync.js';
export const S3GeneralPurposeBucketSync = {
awsService: 's3',
name: 'generalPurposeBuckets',
execute: async (accountId, region, credentials, storage, endpoint, syncOptions) => {
const s3Client = AwsClientPool.defaultInstance.client(S3Client, credentials, region, endpoint);
const allBuckets = await paginateResource(s3Client, ListBucketsCommand, 'Buckets', {
inputKey: 'ContinuationToken',
outputKey: 'ContinuationToken'
}, { MaxBuckets: 1000, BucketRegion: region });
const augmentedBuckets = await Promise.all(allBuckets.map(async (bucket) => {
const [tags, blockPublicAccessConfig, bucketPolicy, encryption] = await Promise.all([
getTagsForBucket(s3Client, bucket),
getBucketPublicAccessSettings(s3Client, bucket),
getBucketPolicy(s3Client, bucket, credentials.accountId),
getBucketEncryptionSettings(s3Client, bucket)
]);
const arn = `arn:${credentials.partition}:s3:::${bucket.Name}`;
return {
arn,
tags: tags,
bpa: blockPublicAccessConfig,
policy: bucketPolicy,
encryption: encryption?.Rules,
metadata: {
name: bucket.Name,
region: region,
arn
}
};
}));
syncData(augmentedBuckets, storage, accountId, {
service: 's3',
account: accountId,
metadata: {
region
}
});
}
};
/**
* Get the tags for a bucket.
*
* @param client the S3 client to use
* @param bucket the bucket to get the tags for
* @returns the tags for the bucket, if any
*/
async function getTagsForBucket(client, bucket) {
const tagCommand = new GetBucketTaggingCommand({ Bucket: bucket.Name });
const tags = await runAndCatch404(async () => {
const response = await client.send(tagCommand);
return response.TagSet?.reduce((acc, tag) => {
acc[tag.Key] = tag.Value;
return acc;
}, {});
});
return tags;
}
/**
* Get the bucket policy for a bucket.
*
* @param client the S3 client to use
* @param bucket the bucket to get the policy for
* @param accountId the account ID of the bucket owner
* @returns the bucket policy for the bucket, if any
*/
async function getBucketPolicy(client, bucket, accountId) {
if (typeof bucket !== 'string') {
bucket = bucket.Name;
}
const policyCommand = new GetBucketPolicyCommand({
Bucket: bucket,
ExpectedBucketOwner: accountId
});
const policy = await runAndCatch404(async () => {
const response = await client.send(policyCommand);
return response.Policy ? JSON.parse(response.Policy) : undefined;
});
return policy;
}
/**
* Get the public access block configuration for a bucket.
*
* @param client The S3 client to use.
* @param bucket the bucket to get the public access settings for
* @returns the public access block configuration for the bucket, if any
*/
async function getBucketPublicAccessSettings(client, bucket) {
const command = new GetPublicAccessBlockCommand({ Bucket: bucket.Name });
const response = await runAndCatch404(async () => {
return await client.send(command);
});
return response?.PublicAccessBlockConfiguration;
}
/**
* Get the bucket encryption settings for a bucket.
*
* @param client the S3 client to use
* @param bucket the bucket to get the encryption settings for
* @returns encryption settings for the bucket, if any
*/
async function getBucketEncryptionSettings(client, bucket) {
const command = new GetBucketEncryptionCommand({ Bucket: bucket.Name });
const response = await runAndCatch404(async () => {
return await client.send(command);
});
return response?.ServerSideEncryptionConfiguration;
}
//# sourceMappingURL=buckets.js.map