diff --git a/cdk/resources/AvatarStorage.ts b/cdk/resources/AvatarStorage.ts new file mode 100644 index 00000000..01dbc106 --- /dev/null +++ b/cdk/resources/AvatarStorage.ts @@ -0,0 +1,38 @@ +import * as CloudFormation from '@aws-cdk/core' +import * as S3 from '@aws-cdk/aws-s3' +import * as IAM from '@aws-cdk/aws-iam' + +/** + * Storage for avatars + */ +export class AvatarStorage extends CloudFormation.Resource { + public readonly bucket: S3.IBucket + public constructor( + parent: CloudFormation.Stack, + id: string, + { userRole }: { userRole: IAM.Role }, + ) { + super(parent, id) + + this.bucket = new S3.Bucket(this, 'bucket', { + publicReadAccess: true, + cors: [ + { + allowedHeaders: ['*'], + allowedMethods: [S3.HttpMethods.GET, S3.HttpMethods.PUT], + allowedOrigins: ['*'], + exposedHeaders: ['Date'], + maxAge: 3600, + }, + ], + removalPolicy: CloudFormation.RemovalPolicy.DESTROY, + }) + + userRole.addToPolicy( + new IAM.PolicyStatement({ + resources: [`${this.bucket.bucketArn}/*`], + actions: ['s3:PutObject'], + }), + ) + } +} diff --git a/cdk/stacks/Bifravst.ts b/cdk/stacks/Bifravst.ts index 7a7b839b..03c0457e 100644 --- a/cdk/stacks/Bifravst.ts +++ b/cdk/stacks/Bifravst.ts @@ -12,6 +12,7 @@ import { BifravstLambdas } from '../cloudformation' import { LayeredLambdas } from '@nrfcloud/package-layered-lambdas' import { WebAppHosting } from '../resources/WebAppHosting' import { RepublishDesiredConfig } from '../resources/RepublishDesiredConfig' +import { AvatarStorage } from '../resources/AvatarStorage' export class BifravstStack extends CloudFormation.Stack { public constructor( @@ -85,7 +86,11 @@ export class BifravstStack extends CloudFormation.Stack { statements: [ new IAM.PolicyStatement({ resources: ['*'], - actions: ['iot:listThings', 'iot:describeThing'], + actions: [ + 'iot:listThings', + 'iot:describeThing', + 'iot:updateThing', + ], }), ], }), @@ -345,6 +350,13 @@ export class BifravstStack extends CloudFormation.Stack { }) new RepublishDesiredConfig(this, 'republishDesiredConfig') + + const avatarStorage = new AvatarStorage(this, 'avatars', { userRole }) + + new CloudFormation.CfnOutput(this, 'avatarBucketName', { + value: avatarStorage.bucket.bucketName, + exportName: `${this.stackName}:avatarBucketName`, + }) } } @@ -363,4 +375,5 @@ export type StackOutputs = { thingPolicyArn: string thingGroupName: string userIotPolicyArn: string + avatarBucket: string }