@cloud-copilot/iam-collect
Version:
Collect IAM information from AWS Accounts
239 lines • 10.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AwsConfigS3Client = void 0;
const client_s3_1 = require("@aws-sdk/client-s3");
const AbstractClient_js_1 = require("../../customClients/AbstractClient.js");
const ResourceNotFoundException_js_1 = require("../../customClients/ResourceNotFoundException.js");
const json_js_1 = require("../../utils/json.js");
const AwsConfigClientContext_js_1 = require("../AwsConfigClientContext.js");
const awsConfigUtils_js_1 = require("../awsConfigUtils.js");
/**
* AWS Config-based S3 client implementation
*/
class AwsConfigS3Client extends AbstractClient_js_1.AbstractClient {
static clientName = client_s3_1.S3Client.name;
constructor(options, customContext) {
super(options, customContext);
}
registerCommands() {
this.registerCommand(AwsConfigGetBucketPolicyCommand);
this.registerCommand(AwsConfigGetBucketEncryptionCommand);
this.registerCommand(AwsConfigGetBucketTaggingCommand);
this.registerCommand(AwsConfigGetPublicAccessBlockCommand);
this.registerCommand(AwsConfigListBucketsCommand);
this.registerCommand(AwsConfigListDirectoryBucketsCommand);
}
}
exports.AwsConfigS3Client = AwsConfigS3Client;
/**
* Config-based implementation of S3 ListBucketsCommand
* Returns bucket listing from AWS Config inventory data
*/
const AwsConfigListBucketsCommand = (0, AwsConfigClientContext_js_1.awsConfigCommand)({
command: client_s3_1.ListBucketsCommand,
execute: async (input, context) => {
// Query Config for S3 buckets
const query = `
SELECT
arn,
resourceName,
configuration.name,
configuration.creationDate,
supplementaryConfiguration.BucketPolicy,
supplementaryConfiguration.ServerSideEncryptionConfiguration,
supplementaryConfiguration.PublicAccessBlockConfiguration,
tags
WHERE
resourceType = 'AWS::S3::Bucket'
AND awsRegion = '${input.BucketRegion}'
AND accountId = '${context.accountId}'
AND ${awsConfigUtils_js_1.resourceStatusWhereClause}
`;
const configResults = await (0, awsConfigUtils_js_1.executeConfigQuery)(query, context);
const buckets = configResults.map((resultString) => {
const { configItem, configuration, supplementaryConfiguration, tags } = (0, awsConfigUtils_js_1.parseConfigItem)(resultString);
context.putCache(configItem.resourceName, 'policy', supplementaryConfiguration?.BucketPolicy.policyText);
context.putCache(configItem.resourceName, 'encryption', supplementaryConfiguration?.ServerSideEncryptionConfiguration);
context.putCache(configItem.resourceName, 'tags', tags);
context.putCache(configItem.resourceName, 'publicAccessBlock', supplementaryConfiguration?.PublicAccessBlockConfiguration);
return {
Name: configuration?.name || configItem.resourceName,
CreationDate: configuration?.creationDate ? new Date(configuration.creationDate) : undefined
};
});
return {
Buckets: buckets
};
}
});
/**
* Config-based implementation of S3 ListDirectoryBucketsCommand
* Uses AWS::S3Express::DirectoryBucket resource type
*/
const AwsConfigListDirectoryBucketsCommand = (0, AwsConfigClientContext_js_1.awsConfigCommand)({
command: client_s3_1.ListDirectoryBucketsCommand,
execute: async (input, context) => {
const query = `
SELECT
arn,
resourceId,
resourceName,
configuration.BucketEncryption,
tags
WHERE
resourceType = 'AWS::S3Express::DirectoryBucket'
AND awsRegion = '${context.region}'
AND accountId = '${context.accountId}'
AND ${awsConfigUtils_js_1.resourceStatusWhereClause}
`;
const results = await (0, awsConfigUtils_js_1.executeConfigQuery)(query, context);
const buckets = results?.map((resultString) => {
const { configItem, configuration } = (0, awsConfigUtils_js_1.parseConfigItem)(resultString);
context.putCache(configItem.resourceName, 'policy', configuration?.PolicyDocument);
context.putCache(configItem.resourceName, 'encryption', configuration?.BucketEncryption);
return {
Name: configItem.resourceName
};
}) || [];
return {
Buckets: buckets
};
}
});
/**
* Config-based implementation of S3 GetBucketPolicyCommand
* Returns bucket policy from AWS Config supplementary data
*/
const AwsConfigGetBucketPolicyCommand = (0, AwsConfigClientContext_js_1.awsConfigCommand)({
command: client_s3_1.GetBucketPolicyCommand,
execute: async (input, context) => {
const { Bucket } = input;
if (!Bucket) {
throw new Error('Bucket parameter is required');
}
if (isDirectoryBucket(Bucket)) {
const query = `
SELECT
resourceName,
configuration.PolicyDocument
WHERE
resourceType = 'AWS::S3Express::BucketPolicy'
AND resourceName = '${Bucket}'
AND accountId = '${context.accountId}'
AND awsRegion = '${context.region}'
AND ${awsConfigUtils_js_1.resourceStatusWhereClause}
`;
const configResults = await (0, awsConfigUtils_js_1.executeConfigQuery)(query, context);
if (configResults.length === 0) {
throw new ResourceNotFoundException_js_1.ResourceNotFoundException(`Bucket '${Bucket}' not found`);
}
const { configuration } = (0, awsConfigUtils_js_1.parseConfigItem)(configResults[0]);
return {
Policy: JSON.stringify(configuration?.PolicyDocument)
};
}
const cachedPolicy = context.getCache(Bucket, 'policy');
return {
Policy: (0, json_js_1.stringifyIfPresent)(cachedPolicy)
};
}
});
/**
* Config-based implementation of S3 GetBucketEncryptionCommand
* Returns bucket encryption configuration from AWS Config supplementary data
*/
const AwsConfigGetBucketEncryptionCommand = (0, AwsConfigClientContext_js_1.awsConfigCommand)({
command: client_s3_1.GetBucketEncryptionCommand,
execute: async (input, context) => {
const { Bucket } = input;
if (!Bucket) {
throw new Error('Bucket parameter is required');
}
if (isDirectoryBucket(Bucket)) {
const encryptionConfig = context.getCache(Bucket, 'encryption');
const seeConfig = encryptionConfig?.ServerSideEncryptionConfiguration?.at(0);
if (!seeConfig) {
// Return an empty result to indicate no encryption configuration is set
return {};
}
return {
ServerSideEncryptionConfiguration: {
Rules: [
{
ApplyServerSideEncryptionByDefault: {
SSEAlgorithm: seeConfig.ServerSideEncryptionByDefault?.SSEAlgorithm,
KMSMasterKeyID: seeConfig.ServerSideEncryptionByDefault?.KMSMasterKeyID
},
BucketKeyEnabled: seeConfig.BucketKeyEnabled
}
]
}
};
}
const serverSideEncryption = context.getCache(Bucket, 'encryption');
if (!serverSideEncryption) {
// Return undefined to indicate no encryption configuration is set
return undefined;
}
// Convert Config encryption format to S3 ServerSideEncryptionConfiguration format
const rules = serverSideEncryption.rules?.map((rule) => ({
ApplyServerSideEncryptionByDefault: {
SSEAlgorithm: rule.applyServerSideEncryptionByDefault?.sseAlgorithm,
KMSMasterKeyID: rule.applyServerSideEncryptionByDefault?.kmsMasterKeyID
},
BucketKeyEnabled: rule.bucketKeyEnabled
})) || [];
return {
ServerSideEncryptionConfiguration: {
Rules: rules
}
};
}
});
/**
* Config-based implementation of S3 GetBucketTaggingCommand
* Returns bucket tags from AWS Config tags data
*/
const AwsConfigGetBucketTaggingCommand = (0, AwsConfigClientContext_js_1.awsConfigCommand)({
command: client_s3_1.GetBucketTaggingCommand,
execute: async (input, context) => {
const { Bucket } = input;
if (!Bucket) {
throw new Error('Bucket parameter is required');
}
const tags = context.getCache(Bucket, 'tags');
return {
TagSet: tags
};
}
});
/**
* Config-based implementation of S3 GetPublicAccessBlockCommand
* Returns public access block configuration from AWS Config supplementary data
*/
const AwsConfigGetPublicAccessBlockCommand = (0, AwsConfigClientContext_js_1.awsConfigCommand)({
command: client_s3_1.GetPublicAccessBlockCommand,
execute: async (input, context) => {
const { Bucket } = input;
if (!Bucket) {
throw new Error('Bucket parameter is required');
}
const publicAccessBlock = context.getCache(Bucket, 'publicAccessBlock');
if (!publicAccessBlock) {
// Return undefined to indicate no public access block configuration is set
return undefined;
}
return {
PublicAccessBlockConfiguration: {
BlockPublicAcls: publicAccessBlock.blockPublicAcls,
BlockPublicPolicy: publicAccessBlock.blockPublicPolicy,
IgnorePublicAcls: publicAccessBlock.ignorePublicAcls,
RestrictPublicBuckets: publicAccessBlock.restrictPublicBuckets
}
};
}
});
function isDirectoryBucket(bucketName) {
return bucketName.endsWith('-x-s3');
}
//# sourceMappingURL=AwsConfigS3Client.js.map