@aws-amplify/amplify-category-storage
Version:
amplify-cli storage plugin
845 lines • 41.5 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AmplifyS3ResourceCfnStack = void 0;
const iamCdk = __importStar(require("aws-cdk-lib/aws-iam"));
const lambdaCdk = __importStar(require("aws-cdk-lib/aws-lambda"));
const s3Cdk = __importStar(require("aws-cdk-lib/aws-s3"));
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
const cdk = __importStar(require("aws-cdk-lib"));
const amplify_cli_core_1 = require("@aws-amplify/amplify-cli-core");
const s3_user_input_types_1 = require("../service-walkthrough-types/s3-user-input-types");
const s3AuthAPI = __importStar(require("../service-walkthroughs/s3-auth-api"));
const s3_user_input_state_1 = require("../service-walkthroughs/s3-user-input-state");
const types_1 = require("./types");
class AmplifyS3ResourceCfnStack extends types_1.AmplifyResourceCfnStack {
constructor(scope, s3ResourceName, props, cfnInputParams) {
super(scope, s3ResourceName);
this.notificationConfiguration = {
lambdaConfigurations: [],
};
this._props = (0, s3_user_input_types_1.defaultS3UserInputs)();
this._cfnInputParams = {};
this.createTriggerLambdaCFNParams = (triggerParameterName, triggerFunction) => {
const triggerFunctionARN = `function${triggerFunction}Arn`;
const triggerFunctionName = `function${triggerFunction}Name`;
const triggerFunctionLambdaExecutionRole = `function${triggerFunction}LambdaExecutionRole`;
const params = [triggerFunctionARN, triggerFunctionName, triggerFunctionLambdaExecutionRole];
const s3CfnTriggerFunctionParams = params.map((param) => ({
params: [param],
paramType: 'String',
default: param,
}));
s3CfnTriggerFunctionParams.push({
params: [triggerParameterName],
paramType: 'String',
});
return s3CfnTriggerFunctionParams;
};
this.emptyNotificationsConfiguration = () => ({
lambdaConfigurations: [],
});
this.isAmplifyStackLegacy = () => {
const amplifyMeta = amplify_cli_core_1.stateManager.getMeta();
const stackName = amplifyMeta.providers.awscloudformation.StackName;
return !stackName.startsWith('amplify-');
};
this.buildCORSRules = () => {
const corsRule = {
id: 'S3CORSRuleId1',
maxAge: 3000,
exposedHeaders: ['x-amz-server-side-encryption', 'x-amz-request-id', 'x-amz-id-2', 'ETag'],
allowedHeaders: ['*'],
allowedOrigins: ['*'],
allowedMethods: [aws_s3_1.HttpMethods.GET, aws_s3_1.HttpMethods.HEAD, aws_s3_1.HttpMethods.PUT, aws_s3_1.HttpMethods.POST, aws_s3_1.HttpMethods.DELETE],
};
const corsConfig = {
corsRules: [corsRule],
};
return corsConfig;
};
this.filterRuleAppendRegionToLambdaTriggerPrefix = (triggerPrefix) => {
const regionRef = cdk.Fn.ref('AWS::Region');
const filterRule = {
name: 'prefix',
value: cdk.Fn.join('', [triggerPrefix.prefix, regionRef]),
};
return filterRule;
};
this.filterRulePlainStringLambdaTriggerPrefix = (triggerPrefix) => {
const filterRule = {
name: 'prefix',
value: triggerPrefix.prefix,
};
return filterRule;
};
this.buildTriggerPrefixRule = (triggerPrefix) => {
if (triggerPrefix.prefixTransform === s3_user_input_types_1.S3TriggerPrefixTransform.ATTACH_REGION) {
const filterRule = this.filterRuleAppendRegionToLambdaTriggerPrefix(triggerPrefix);
return filterRule;
}
const filterRule = this.filterRulePlainStringLambdaTriggerPrefix(triggerPrefix);
return filterRule;
};
this.createAndSetIAMPolicies = () => {
if (this._cfnInputParams.s3PermissionsAuthenticatedPublic !== types_1.AmplifyBuildParamsPermissions.DISALLOW) {
this.s3AuthPublicPolicy = this.createS3AuthPublicPolicy();
}
if (this._cfnInputParams.s3PermissionsAuthenticatedProtected !== types_1.AmplifyBuildParamsPermissions.DISALLOW) {
this.s3AuthProtectedPolicy = this.createS3AuthProtectedPolicy();
}
if (this._cfnInputParams.s3PermissionsAuthenticatedPrivate !== types_1.AmplifyBuildParamsPermissions.DISALLOW) {
this.s3AuthPrivatePolicy = this.createS3AuthPrivatePolicy();
}
if (this._cfnInputParams.s3PermissionsAuthenticatedUploads !== types_1.AmplifyBuildParamsPermissions.DISALLOW) {
this.s3AuthUploadPolicy = this.createS3AuthUploadPolicy();
}
if (this._cfnInputParams.s3PermissionsGuestPublic !== types_1.AmplifyBuildParamsPermissions.DISALLOW) {
this.s3GuestPublicPolicy = this.createS3GuestPublicPolicy();
}
if (this._cfnInputParams.s3PermissionsGuestUploads !== types_1.AmplifyBuildParamsPermissions.DISALLOW) {
this.s3GuestUploadPolicy = this.createGuestUploadsPolicy();
}
this.s3AuthReadPolicy = this.createS3AuthReadPolicy();
this.s3GuestReadPolicy = this.createS3GuestReadPolicy();
};
this.createS3IAMPolicyDocument = (refStr, pathStr, actionStr, effect) => {
const props = {
resources: [cdk.Fn.join('', ['arn:aws:s3:::', cdk.Fn.ref(refStr), pathStr])],
actions: cdk.Fn.split(',', cdk.Fn.ref(actionStr)),
effect,
};
const policyDocument = new iamCdk.PolicyDocument();
const policyStatement = new iamCdk.PolicyStatement(props);
policyDocument.addStatements(policyStatement);
return policyDocument;
};
this.createMultiStatementIAMPolicyDocument = (policyStatements) => {
const policyDocument = new iamCdk.PolicyDocument();
policyStatements.forEach((policyStatement) => {
const props = {
resources: policyStatement.pathStr
? [cdk.Fn.join('', ['arn:aws:s3:::', cdk.Fn.ref(policyStatement.refStr), policyStatement.pathStr])]
: [cdk.Fn.join('', ['arn:aws:s3:::', cdk.Fn.ref(policyStatement.refStr)])],
conditions: policyStatement.conditions,
actions: policyStatement.actions,
effect: policyStatement.effect,
};
const statement = new iamCdk.PolicyStatement(props);
policyDocument.addStatements(statement);
});
return policyDocument;
};
this.createS3AuthPublicPolicy = () => {
const policyDefinition = {
logicalId: 'S3AuthPublicPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3PublicPolicy',
roleRefs: ['authRoleName'],
condition: this.conditions.CreateAuthPublic,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/public/*',
actions: ['s3PermissionsAuthenticatedPublic'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createIAMPolicy(policyDefinition, true);
return policy;
};
this.createS3AuthProtectedPolicy = () => {
const policyDefinition = {
logicalId: 'S3AuthProtectedPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3ProtectedPolicy',
roleRefs: ['authRoleName'],
condition: this.conditions.CreateAuthProtected,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/protected/${cognito-identity.amazonaws.com:sub}/*',
actions: ['s3PermissionsAuthenticatedProtected'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createIAMPolicy(policyDefinition, true);
return policy;
};
this.createS3AuthPrivatePolicy = () => {
const policyDefinition = {
logicalId: 'S3AuthPrivatePolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3PrivatePolicy',
roleRefs: ['authRoleName'],
condition: this.conditions.CreateAuthPrivate,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/private/${cognito-identity.amazonaws.com:sub}/*',
actions: ['s3PermissionsAuthenticatedPrivate'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createIAMPolicy(policyDefinition, true);
return policy;
};
this.createS3AuthUploadPolicy = () => {
const policyDefinition = {
logicalId: 'S3AuthUploadPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3UploadsPolicy',
roleRefs: ['authRoleName'],
condition: this.conditions.CreateAuthUploads,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/uploads/*',
actions: ['s3PermissionsAuthenticatedUploads'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createIAMPolicy(policyDefinition, true);
return policy;
};
this.createS3GuestPublicPolicy = () => {
const policyDefinition = {
logicalId: 'S3GuestPublicPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3PublicPolicy',
roleRefs: ['unauthRoleName'],
condition: this.conditions.CreateGuestPublic,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/public/*',
actions: ['s3PermissionsGuestPublic'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createIAMPolicy(policyDefinition, true);
return policy;
};
this.createGuestUploadsPolicy = () => {
const policyDefinition = {
logicalId: 'S3GuestUploadPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3UploadsPolicy',
roleRefs: ['unauthRoleName'],
condition: this.conditions.CreateGuestUploads,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/uploads/*',
actions: ['s3PermissionsGuestUploads'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createIAMPolicy(policyDefinition, true);
return policy;
};
this.createS3AuthReadPolicy = () => {
const policyDefinition = {
logicalId: 'S3AuthReadPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3ReadPolicy',
roleRefs: ['authRoleName'],
condition: this.conditions.CreateAuthReadAndList,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/protected/*',
actions: ['s3:GetObject'],
effect: iamCdk.Effect.ALLOW,
},
{
refStr: 'S3Bucket',
actions: ['s3:ListBucket'],
conditions: {
StringLike: {
's3:prefix': [
'public/',
'public/*',
'protected/',
'protected/*',
'private/${cognito-identity.amazonaws.com:sub}/',
'private/${cognito-identity.amazonaws.com:sub}/*',
],
},
},
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createMultiStatementIAMPolicy(policyDefinition);
return policy;
};
this.createS3GuestReadPolicy = () => {
const policyDefinition = {
logicalId: 'S3GuestReadPolicy',
isPolicyNameAbsolute: false,
policyNameRef: 's3ReadPolicy',
roleRefs: ['unauthRoleName'],
condition: this.conditions.CreateGuestReadAndList,
statements: [
{
refStr: 'S3Bucket',
pathStr: '/protected/*',
actions: ['s3:GetObject'],
effect: iamCdk.Effect.ALLOW,
},
{
refStr: 'S3Bucket',
actions: ['s3:ListBucket'],
conditions: {
StringLike: {
's3:prefix': ['public/', 'public/*', 'protected/', 'protected/*'],
},
},
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
const policy = this.createMultiStatementIAMPolicy(policyDefinition);
return policy;
};
this.addFunctionToTriggerPolicyDefinition = (policyDefinition, functionName) => {
const newRoleRef = `function${functionName}LambdaExecutionRole`;
const newPolicyDefinition = policyDefinition;
if (policyDefinition.roleRefs && policyDefinition.roleRefs.includes(newRoleRef)) {
return policyDefinition;
}
newPolicyDefinition.roleRefs = policyDefinition.roleRefs ? policyDefinition.roleRefs.concat([newRoleRef]) : [newRoleRef];
return newPolicyDefinition;
};
this.createTriggerPolicyFromPolicyDefinition = (policyDefinition) => {
const policy = this.createIAMPolicy(policyDefinition, false);
return policy;
};
this.buildResourceFromPolicyDefinition = (policyDefinitionStatement) => {
const resourceStrArr = ['arn:aws:s3:::', { Ref: policyDefinitionStatement.refStr }];
if (policyDefinitionStatement.pathStr && policyDefinitionStatement.pathStr.length > 0) {
resourceStrArr.push(policyDefinitionStatement.pathStr);
}
return {
'Fn::Join': ['', resourceStrArr],
};
};
this.buildActionFromPolicyDefinition = (policyDefinitionStatement, IsActionRef) => {
if (!policyDefinitionStatement.actions) {
return [];
}
if (!policyDefinitionStatement.isActionAbsolute && IsActionRef === true) {
const actionRef = policyDefinitionStatement.actions[0];
const actions = {
'Fn::Split': [
',',
{
Ref: actionRef,
},
],
};
return actions;
}
return policyDefinitionStatement.actions;
};
this.createMultiStatementIAMPolicy = (policyDefinition) => {
const props = {
policyName: cdk.Fn.ref(policyDefinition.policyNameRef),
roles: policyDefinition.roleRefs.map((roleRef) => cdk.Fn.ref(roleRef)),
policyDocument: this.createMultiStatementIAMPolicyDocument(policyDefinition.statements),
};
const policy = new iamCdk.CfnPolicy(this, policyDefinition.logicalId, props);
if (policyDefinition.dependsOn) {
policyDefinition.dependsOn.map((dependency) => policy.addDependency(dependency));
}
if (policyDefinition.condition) {
policy.cfnOptions.condition = policyDefinition.condition;
}
return policy;
};
this.buildGroupPolicyLogicalID = (groupName) => `${groupName}GroupPolicy`;
this.buildGroupPolicyName = (groupName) => `${groupName}-group-s3-policy`;
this.buildGroupRoleName = (groupName) => `${groupName}GroupRole`;
this.buildCDKGroupRoles = (groupName, authResourceName) => {
const roles = [cdk.Fn.join('', [cdk.Fn.ref(`auth${authResourceName}UserPoolId`), `-${this.buildGroupRoleName(groupName)}`])];
return roles;
};
this._buildCDKGroupPolicyStatements = (groupPerms) => {
const policyStatementList = [];
const bucketArn = cdk.Fn.join('', ['arn:aws:s3:::', cdk.Fn.ref('S3Bucket')]).toString();
const permissions = s3_user_input_state_1.S3InputState.getCfnPermissionsFromInputPermissions(groupPerms);
policyStatementList.push(new iamCdk.PolicyStatement({
resources: [`${bucketArn}/*`],
actions: permissions,
effect: iamCdk.Effect.ALLOW,
}));
if (groupPerms.includes(s3_user_input_types_1.S3PermissionType.READ)) {
policyStatementList.push(new iamCdk.PolicyStatement({
resources: [`${bucketArn}`],
actions: [s3_user_input_state_1.S3CFNPermissionType.LIST],
effect: iamCdk.Effect.ALLOW,
}));
}
return policyStatementList;
};
this._buildCDKGroupPolicyDocument = (policyStatementList) => {
const policyDocument = new iamCdk.PolicyDocument();
policyStatementList.forEach((policyStatement) => {
policyDocument.addStatements(policyStatement);
});
return policyDocument;
};
this._setCFNParams = (paramDefinitions) => {
paramDefinitions.params.forEach((paramName) => {
const cfnParam = {
type: paramDefinitions.paramType,
};
if (paramDefinitions.default) {
cfnParam.default = paramDefinitions.default;
}
this.addCfnParameter(cfnParam, paramName);
});
};
this.buildS3DependsOnFunctionCfn = (functionName) => {
const s3DependsOnLambda = {
category: 'function',
resourceName: functionName,
attributes: ['Name', 'Arn', 'LambdaExecutionRole'],
};
return s3DependsOnLambda;
};
this.buildS3DependsOnUserPoolIdCfn = (authResourceName) => {
const dependsOnAuth = {
category: 'auth',
resourceName: authResourceName,
attributes: ['UserPoolId'],
};
return dependsOnAuth;
};
this.buildS3DependsOnUserPoolGroupRoleListCfn = (selectedUserPoolGroupList) => {
if (selectedUserPoolGroupList && selectedUserPoolGroupList.length > 0) {
const userPoolGroupRoleList = selectedUserPoolGroupList.map((groupName) => {
const dependsOnAuth = {
category: 'auth',
resourceName: 'userPoolGroups',
attributes: [`${groupName}GroupRole`],
};
return dependsOnAuth;
});
return userPoolGroupRoleList;
}
return [];
};
this.scope = scope;
this.id = s3ResourceName;
this._props = props;
this._cfnInputParams = cfnInputParams;
this.templateOptions.templateFormatVersion = CFN_TEMPLATE_FORMAT_VERSION;
this.templateOptions.description = S3_ROOT_CFN_DESCRIPTION;
this.s3BucketName = this.buildBucketName();
this.s3DependsOnResources = [];
this.notificationConfiguration = {
lambdaConfigurations: [],
};
}
getGroupListFromProps() {
const groupList = this._props.groupAccess ? Object.keys(this._props.groupAccess) : [];
return groupList;
}
getS3ResourceFriendlyName() {
return this.id;
}
getS3BucketName() {
return this.s3BucketName;
}
getS3DependsOn() {
return this.s3DependsOnResources;
}
_addNotificationsLambdaConfigurations(newLambdaConfigurations) {
const existingLambdaConfigurations = this.notificationConfiguration.lambdaConfigurations;
this.notificationConfiguration = {
lambdaConfigurations: existingLambdaConfigurations.concat(newLambdaConfigurations),
};
}
configureTriggerPolicy() {
var _a;
let s3TriggerPolicyDefinition;
if (this._props.triggerFunction && this._props.triggerFunction !== 'NONE') {
s3TriggerPolicyDefinition = this.createTriggerPolicyDefinition('S3TriggerBucketPolicy', this._props.triggerFunction);
}
if (((_a = this._props.adminTriggerFunction) === null || _a === void 0 ? void 0 : _a.triggerFunction) &&
this._props.adminTriggerFunction.triggerFunction !== 'NONE' &&
this._props.adminTriggerFunction.triggerFunction !== this._props.triggerFunction) {
const adminTriggerFunctionName = this._props.adminTriggerFunction.triggerFunction;
s3TriggerPolicyDefinition = s3TriggerPolicyDefinition
? this.addFunctionToTriggerPolicyDefinition(s3TriggerPolicyDefinition, adminTriggerFunctionName)
: this.createTriggerPolicyDefinition('S3TriggerBucketPolicy', adminTriggerFunctionName);
}
if (s3TriggerPolicyDefinition) {
this.s3TriggerPolicy = this.createTriggerPolicyFromPolicyDefinition(s3TriggerPolicyDefinition);
}
}
_conditionallyBuildTriggerLambdaParams(triggerFunction) {
var _a;
let triggerLambdaFunctionParams;
if (((_a = this._props.adminTriggerFunction) === null || _a === void 0 ? void 0 : _a.triggerFunction) &&
this._props.adminTriggerFunction.triggerFunction !== 'NONE' &&
this._props.adminTriggerFunction.triggerFunction !== this._props.triggerFunction) {
triggerLambdaFunctionParams = {
category: amplify_cli_core_1.AmplifyCategories.STORAGE,
tag: 'triggerFunction',
triggerFunction,
permissions: [s3_user_input_types_1.S3PermissionType.CREATE_AND_UPDATE, s3_user_input_types_1.S3PermissionType.READ, s3_user_input_types_1.S3PermissionType.DELETE],
triggerEvents: [s3_user_input_types_1.S3TriggerEventType.OBJ_PUT_POST_COPY, s3_user_input_types_1.S3TriggerEventType.OBJ_REMOVED],
triggerPrefix: [
{ prefix: 'protected/', prefixTransform: s3_user_input_types_1.S3TriggerPrefixTransform.ATTACH_REGION },
{ prefix: 'private/', prefixTransform: s3_user_input_types_1.S3TriggerPrefixTransform.ATTACH_REGION },
{ prefix: 'public/', prefixTransform: s3_user_input_types_1.S3TriggerPrefixTransform.ATTACH_REGION },
],
};
}
else {
triggerLambdaFunctionParams = {
category: amplify_cli_core_1.AmplifyCategories.STORAGE,
tag: 'triggerFunction',
triggerFunction,
permissions: [s3_user_input_types_1.S3PermissionType.CREATE_AND_UPDATE, s3_user_input_types_1.S3PermissionType.READ, s3_user_input_types_1.S3PermissionType.DELETE],
triggerEvents: [s3_user_input_types_1.S3TriggerEventType.OBJ_PUT_POST_COPY, s3_user_input_types_1.S3TriggerEventType.OBJ_REMOVED],
};
}
return triggerLambdaFunctionParams;
}
async generateCfnStackResources(context) {
var _a;
this.s3Bucket = new s3Cdk.CfnBucket(this, 'S3Bucket', {
bucketName: this.s3BucketName,
corsConfiguration: this.buildCORSRules(),
});
this.s3Bucket.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);
if (this._props.triggerFunction && this._props.triggerFunction !== 'NONE') {
const triggerLambdaFunctionParams = this._conditionallyBuildTriggerLambdaParams(this._props.triggerFunction);
const newLambdaConfigurations = this.buildLambdaConfigFromTriggerParams(triggerLambdaFunctionParams);
this._addNotificationsLambdaConfigurations(newLambdaConfigurations);
this.triggerLambdaPermissions = this.createInvokeFunctionS3Permission('TriggerPermissions', this._props.triggerFunction);
this.s3Bucket.addDependency(this.triggerLambdaPermissions);
this.s3DependsOnResources.push(this.buildS3DependsOnFunctionCfn(this._props.triggerFunction));
}
if (((_a = this._props.adminTriggerFunction) === null || _a === void 0 ? void 0 : _a.triggerFunction) &&
this._props.adminTriggerFunction.triggerFunction !== 'NONE' &&
this._props.adminTriggerFunction.triggerFunction !== this._props.triggerFunction) {
const adminLambdaConfigurations = this.buildLambdaConfigFromTriggerParams(this._props.adminTriggerFunction);
this._addNotificationsLambdaConfigurations(adminLambdaConfigurations);
this.adminTriggerLambdaPermissions = this.createInvokeFunctionS3Permission('AdminTriggerPermissions', this._props.adminTriggerFunction.triggerFunction);
this.s3Bucket.addDependency(this.adminTriggerLambdaPermissions);
this.s3DependsOnResources.push(this.buildS3DependsOnFunctionCfn(this._props.adminTriggerFunction.triggerFunction));
}
if (this.notificationConfiguration.lambdaConfigurations &&
this.notificationConfiguration.lambdaConfigurations.length > 0) {
this.s3Bucket.notificationConfiguration = this.notificationConfiguration;
}
this.createAndSetIAMPolicies();
const groupList = this.getGroupListFromProps();
if (groupList && groupList.length > 0) {
const authResourceName = await s3AuthAPI.getAuthResourceARN(context);
this.authResourceName = authResourceName;
this.s3GroupPolicyList = this.createS3AmplifyGroupPolicies(authResourceName, groupList, this._props.groupAccess);
this.addGroupParams(authResourceName);
this.s3DependsOnResources.push(this.buildS3DependsOnUserPoolIdCfn(authResourceName));
const userPoolGroupList = this.buildS3DependsOnUserPoolGroupRoleListCfn(groupList);
this.s3DependsOnResources = this.s3DependsOnResources.concat(userPoolGroupList);
}
this.configureTriggerPolicy();
}
addGroupParams(authResourceName) {
const groupList = this.getGroupListFromProps();
if (groupList && groupList.length > 0) {
const s3CfnParams = [
{
params: [`auth${authResourceName}UserPoolId`],
paramType: 'String',
default: `auth${authResourceName}UserPoolId`,
},
];
for (const groupName of groupList) {
s3CfnParams.push({
params: [`authuserPoolGroups${this.buildGroupRoleName(groupName)}`],
paramType: 'String',
default: `authuserPoolGroups${this.buildGroupRoleName(groupName)}`,
});
}
s3CfnParams.map((params) => this._setCFNParams(params));
}
return undefined;
}
addParameters() {
var _a;
let s3CfnParams = [
{
params: ['env', 'bucketName', 'authRoleName', 'unauthRoleName', 'authPolicyName', 'unauthPolicyName'],
paramType: 'String',
},
{
params: ['s3PublicPolicy', 's3PrivatePolicy', 's3ProtectedPolicy', 's3UploadsPolicy', 's3ReadPolicy'],
paramType: 'String',
default: 'NONE',
},
{
params: [
's3PermissionsAuthenticatedPublic',
's3PermissionsAuthenticatedProtected',
's3PermissionsAuthenticatedPrivate',
's3PermissionsAuthenticatedUploads',
's3PermissionsGuestPublic',
's3PermissionsGuestUploads',
'AuthenticatedAllowList',
'GuestAllowList',
],
paramType: 'String',
default: types_1.AmplifyBuildParamsPermissions.DISALLOW,
},
{
params: ['selectedGuestPermissions', 'selectedAuthenticatedPermissions'],
paramType: 'CommaDelimitedList',
default: 'NONE',
},
];
if (this._props.triggerFunction && this._props.triggerFunction !== 'NONE') {
const triggerFunctionCFNParams = this.createTriggerLambdaCFNParams('triggerFunction', this._props.triggerFunction);
s3CfnParams = s3CfnParams.concat(triggerFunctionCFNParams);
}
if (((_a = this._props.adminTriggerFunction) === null || _a === void 0 ? void 0 : _a.triggerFunction) &&
this._props.adminTriggerFunction.triggerFunction !== 'NONE' &&
this._props.adminTriggerFunction.triggerFunction !== this._props.triggerFunction) {
const adminTriggerFunctionCFNParams = this.createTriggerLambdaCFNParams('adminTriggerFunction', this._props.adminTriggerFunction.triggerFunction);
s3CfnParams = s3CfnParams.concat(adminTriggerFunctionCFNParams);
}
s3CfnParams.map((params) => this._setCFNParams(params));
}
addConditions() {
this.conditions = {
ShouldNotCreateEnvResources: new cdk.CfnCondition(this, 'ShouldNotCreateEnvResources', {
expression: cdk.Fn.conditionEquals(cdk.Fn.ref('env'), 'NONE'),
}),
CreateAuthPublic: new cdk.CfnCondition(this, 'CreateAuthPublic', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('s3PermissionsAuthenticatedPublic'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateAuthProtected: new cdk.CfnCondition(this, 'CreateAuthProtected', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('s3PermissionsAuthenticatedProtected'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateAuthPrivate: new cdk.CfnCondition(this, 'CreateAuthPrivate', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('s3PermissionsAuthenticatedPrivate'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateAuthUploads: new cdk.CfnCondition(this, 'CreateAuthUploads', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('s3PermissionsAuthenticatedUploads'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateGuestPublic: new cdk.CfnCondition(this, 'CreateGuestPublic', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('s3PermissionsGuestPublic'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateGuestUploads: new cdk.CfnCondition(this, 'CreateGuestUploads', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('s3PermissionsGuestUploads'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateAuthReadAndList: new cdk.CfnCondition(this, 'AuthReadAndList', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('AuthenticatedAllowList'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
CreateGuestReadAndList: new cdk.CfnCondition(this, 'GuestReadAndList', {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(cdk.Fn.ref('GuestAllowList'), types_1.AmplifyBuildParamsPermissions.DISALLOW)),
}),
};
return this.conditions;
}
addOutputs() {
this.addCfnOutput({
value: cdk.Fn.ref('S3Bucket'),
description: 'Bucket name for the S3 bucket',
}, 'BucketName');
this.addCfnOutput({
value: cdk.Fn.ref('AWS::Region'),
}, 'Region');
}
buildBucketName() {
const bucketRef = cdk.Fn.ref('bucketName');
const envRef = cdk.Fn.ref('env');
const bucketNameSuffixRef = cdk.Fn.select(3, cdk.Fn.split('-', cdk.Fn.ref('AWS::StackName')));
const bucketFinalName = this.isAmplifyStackLegacy()
? cdk.Fn.join('', [bucketRef, '-', envRef])
: cdk.Fn.join('', [bucketRef, bucketNameSuffixRef, '-', envRef]);
return cdk.Fn.conditionIf('ShouldNotCreateEnvResources', bucketRef, bucketFinalName).toString();
}
buildNotificationLambdaConfiguration() {
const triggerFunctionArnRef = cdk.Fn.ref(`function${this._props.triggerFunction}Arn`);
const lambdaConfigurations = [
{
event: 's3:ObjectCreated:*',
function: triggerFunctionArnRef,
},
{
event: 's3:ObjectRemoved:*',
function: triggerFunctionArnRef,
},
];
return lambdaConfigurations;
}
buildLambdaConfigFromTriggerParams(functionParams) {
const lambdaConfigurations = [];
const triggerFunctionArnRef = cdk.Fn.ref(`function${functionParams.triggerFunction}Arn`);
if (functionParams.permissions) {
for (const triggerEvent of functionParams.triggerEvents) {
if (functionParams.triggerPrefix) {
for (const triggerPrefixDefinition of functionParams.triggerPrefix) {
const lambdaConfig = {
event: triggerEvent,
function: triggerFunctionArnRef,
filter: {
s3Key: {
rules: [this.buildTriggerPrefixRule(triggerPrefixDefinition)],
},
},
};
lambdaConfigurations.push(lambdaConfig);
}
}
else {
const lambdaConfig = {
event: triggerEvent,
function: triggerFunctionArnRef,
};
lambdaConfigurations.push(lambdaConfig);
}
}
}
return lambdaConfigurations;
}
createInvokeFunctionS3Permission(logicalId, triggerFunctionName) {
const sourceArn = cdk.Fn.join('', ['arn:aws:s3:::', this.buildBucketName()]);
const resourceDefinition = {
action: 'lambda:InvokeFunction',
functionName: cdk.Fn.ref(`function${triggerFunctionName}Name`),
principal: 's3.amazonaws.com',
sourceAccount: cdk.Fn.ref('AWS::AccountId'),
sourceArn,
};
const lambdaPermission = new lambdaCdk.CfnPermission(this, logicalId, resourceDefinition);
return lambdaPermission;
}
createTriggerPolicyDefinition(logicalId, triggerFunctionName) {
const policyDefinition = {
logicalId,
isPolicyNameAbsolute: true,
policyNameRef: 'amplify-lambda-execution-policy-storage',
roleRefs: [`function${triggerFunctionName}LambdaExecutionRole`],
statements: [
{
refStr: 'S3Bucket',
pathStr: '',
isActionAbsolute: true,
actions: ['s3:ListBucket'],
effect: iamCdk.Effect.ALLOW,
},
{
refStr: 'S3Bucket',
pathStr: '/*',
isActionAbsolute: true,
actions: ['s3:PutObject', 's3:GetObject', 's3:ListBucket', 's3:DeleteObject'],
effect: iamCdk.Effect.ALLOW,
},
],
dependsOn: [this.s3Bucket],
};
return policyDefinition;
}
createIAMPolicy(policyDefinition, actionRef) {
const policyL1 = {};
policyL1.Properties = {};
if (policyDefinition.isPolicyNameAbsolute) {
policyL1.Properties.policyName = policyDefinition.policyNameRef;
}
else {
policyL1.Properties.policyName = {
Ref: policyDefinition.policyNameRef,
};
}
policyL1.Properties.roles = policyDefinition.roleRefs.map((roleRef) => ({
Ref: roleRef,
}));
policyL1.Properties.policyDocument = {
Version: '2012-10-17',
Statement: [],
};
const policyStatements = [];
for (const policyDefinitionStatement of policyDefinition.statements) {
const policyStatement = {};
policyStatement.Effect = policyDefinitionStatement.effect;
if (policyDefinitionStatement.actions) {
policyStatement.Action = this.buildActionFromPolicyDefinition(policyDefinitionStatement, actionRef);
}
policyStatement.Resource = [this.buildResourceFromPolicyDefinition(policyDefinitionStatement)];
policyStatements.push(policyStatement);
}
policyL1.Properties.policyDocument.Statement = policyStatements;
const policy = new iamCdk.CfnPolicy(this, policyDefinition.logicalId, policyL1.Properties);
if (policyDefinition.dependsOn) {
policyDefinition.dependsOn.map((dependency) => policy.addDependency(dependency));
}
if (policyDefinition.condition) {
policy.cfnOptions.condition = policyDefinition.condition;
}
return policy;
}
createS3AmplifyGroupPolicies(authResourceName, groupList, groupPolicyMap) {
const groupPolicyList = [];
for (const groupName of groupList) {
const logicalID = this.buildGroupPolicyLogicalID(groupName);
const groupPolicyName = this.buildGroupPolicyName(groupName);
const policyStatementList = this._buildCDKGroupPolicyStatements(groupPolicyMap[groupName]);
const props = {
policyName: groupPolicyName,
roles: this.buildCDKGroupRoles(groupName, authResourceName),
policyDocument: this._buildCDKGroupPolicyDocument(policyStatementList),
};
const groupPolicy = new iamCdk.CfnPolicy(this, logicalID, props);
groupPolicyList.push(groupPolicy);
}
return groupPolicyList;
}
}
exports.AmplifyS3ResourceCfnStack = AmplifyS3ResourceCfnStack;
const CFN_TEMPLATE_FORMAT_VERSION = '2010-09-09';
const S3_ROOT_CFN_DESCRIPTION = 'S3 Resource for AWS Amplify CLI';
//# sourceMappingURL=s3-stack-builder.js.map