diff --git a/cloudformation/user-s3.yml b/cloudformation/user-s3.yml new file mode 100644 index 00000000..02e8e1d6 --- /dev/null +++ b/cloudformation/user-s3.yml @@ -0,0 +1,86 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: AWS S3 resources for Givesource(R) +Parameters: + BucketIdentifier: + Type: String + + ReplicaRegion: + Type: String + Default: '' + AllowedValues: + - '' + - 'us-west-2' + - 'us-east-1' + +Conditions: + NotReplicaRegion: !Not [!Equals [!Ref "AWS::Region", !Ref ReplicaRegion]] + +Resources: + StorageBucket: + Condition: NotReplicaRegion + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub givesource-${BucketIdentifier} + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + LoggingConfiguration: + DestinationBucketName: !ImportValue AccessLoggingBucket + LogFilePrefix: !Sub givesource-${BucketIdentifier}/ + + StorageBucketPolicy: + Condition: NotReplicaRegion + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref StorageBucket + PolicyDocument: + Version: 2012-10-17 + Statement: + Sid: allow-ssl-requests-only + Effect: Deny + Principal: '*' + Action: s3:* + Resource: !Sub ${StorageBucket.Arn}/* + Condition: + Bool: + aws:SecureTransport: false + + LambdaBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub givesource-${BucketIdentifier}-${AWS::Region} + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + LoggingConfiguration: + DestinationBucketName: !ImportValue AccessLoggingBucket + LogFilePrefix: !Sub givesource-${BucketIdentifier}-${AWS::Region}/ + + LambdaBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref LambdaBucket + PolicyDocument: + Version: 2012-10-17 + Statement: + Sid: allow-ssl-requests-only + Effect: Deny + Principal: '*' + Action: s3:* + Resource: !Sub ${LambdaBucket.Arn}/* + Condition: + Bool: + aws:SecureTransport: false diff --git a/cloudformation/vpc.yml b/cloudformation/vpc.yml new file mode 100644 index 00000000..2a60f262 --- /dev/null +++ b/cloudformation/vpc.yml @@ -0,0 +1,388 @@ +--- +Description: Creates the VPC, routing tables, and subnets for Givesource +Mappings: + IpRange: + us-east-1: + '016226103026': '172.32' + '948629139753': '172.132' + us-east-2: + '016226103026': '172.33' + '948629139753': '172.133' + us-west-1: + '016226103026': '172.34' + '948629139753': '172.134' + us-west-2: + '016226103026': '172.35' + '948629139753': '172.135' + +Resources: + internetGateway: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: givesource + + vpc: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Sub + - ${IpRange}.0.0/16 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: givesource + - Key: Purpose + Value: The VPC for Givesource + + flowLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub FlowLog/givesource/${vpc} + RetentionInDays: 365 + + flowLogsRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: vpc-flow-logs.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: flowlog-log + PolicyDocument: + Statement: + - Effect: Allow + Action: + - ec2:CreateFlowLogs + Resource: '*' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy + + flowLog: + Type: AWS::EC2::FlowLog + Properties: + DeliverLogsPermissionArn: !GetAtt flowLogsRole.Arn + LogGroupName: !Ref flowLogGroup + ResourceId: !Ref vpc + ResourceType: VPC + TrafficType: ALL + + attachInternetGatewayToVpc: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + InternetGatewayId: !Ref internetGateway + VpcId: !Ref vpc + + publicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: public-givesource + + internetGatewayRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref publicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref internetGateway + + primaryPublicSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref primaryPublicSubnet + RouteTableId: !Ref publicRouteTable + + primaryPublicSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.0.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [0, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Public + - Key: Name + Value: primary-public-givesource + + secondaryPublicSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref secondaryPublicSubnet + RouteTableId: !Ref publicRouteTable + + secondaryPublicSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.2.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [1, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Public + - Key: Name + Value: secondary-public-givesource + + primaryPrivateEip: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + + primaryPrivateNatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt primaryPrivateEip.AllocationId + SubnetId: !Ref primaryPublicSubnet + + primaryPrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: primary-private-givesource + + primaryPrivateRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref primaryPrivateRouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref primaryPrivateNatGateway + + primaryPrivateSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.10.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [0, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Private + - Key: Name + Value: primary-private-givesource + + primaryPrivateSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref primaryPrivateSubnet + RouteTableId: !Ref primaryPrivateRouteTable + + secondaryPrivateEip: + Type: AWS::EC2::EIP + Properties: + Domain: vpc + + secondaryPrivateNatGateway: + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt secondaryPrivateEip.AllocationId + SubnetId: !Ref secondaryPublicSubnet + + secondaryPrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref vpc + Tags: + - Key: Name + Value: secondary-private-givesource + + secondaryPrivateRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref secondaryPrivateRouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref secondaryPrivateNatGateway + + secondaryPrivateSubnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref vpc + CidrBlock: !Sub + - ${IpRange}.12.0/23 + - {IpRange: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId']} + AvailabilityZone: !Select [1, !GetAZs {Ref: 'AWS::Region'}] + Tags: + - Key: SubnetType + Value: Private + - Key: Name + Value: secondary-private-givesource + + secondaryPrivateSubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref secondaryPrivateSubnet + RouteTableId: !Ref secondaryPrivateRouteTable + + vpcDashboard: + Type: AWS::CloudWatch::Dashboard + Properties: + DashboardName: !Sub givesource-vpc-${AWS::Region} + DashboardBody: !Sub + - > + { + "start": "-P6M", + "widgets": [ + { + "type": "metric", + "x": 0, + "y": 0, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/NATGateway", + "BytesInFromSource", + "NatGatewayId", + "${primaryPrivateNatGateway}", + { + "period": 3600 + } + ], + [ + ".", + "BytesInFromSource", + ".", + "${secondaryPrivateNatGateway}", + { + "period": 3600 + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "${AWS::Region}", + "period": 300, + "title": "NAT Gateway Bytes received from clients in your VPC" + } + }, + { + "type": "metric", + "x": 0, + "y": 6, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/NATGateway", + "BytesInFromDestination", + "NatGatewayId", + "${primaryPrivateNatGateway}", + { + "period": 3600 + } + ], + [ + ".", + "BytesInFromDestination", + ".", + "${secondaryPrivateNatGateway}", + { + "period": 3600 + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "${AWS::Region}", + "title": "NAT Gateway Bytes received from the destination" + } + }, + { + "type": "metric", + "x": 0, + "y": 12, + "width": 24, + "height": 6, + "properties": { + "metrics": [ + [ + "AWS/Billing", + "EstimatedCharges", + "Currency", + "USD", + { + "period": 2592000, + "stat": "Maximum" + } + ] + ], + "view": "timeSeries", + "stacked": true, + "region": "us-east-1" + } + } + ] + } + - {} + +Outputs: + internetGateway: + Description: Internet Gateway for the Givesource VPC + Value: !Ref internetGateway + Export: + Name: givesource-internet-gateway + + vpc: + Description: VPC for Givesource + Value: !Ref vpc + Export: + Name: givesource-vpc + + vpcCidr: + Description: The Cidr of the Givesource VPC + Value: !GetAtt vpc.CidrBlock + Export: + Name: givesource-vpc-cidr + + aclVpc: + Description: Default ACL for the Givesource VPC + Value: !GetAtt vpc.DefaultNetworkAcl + Export: + Name: givesource-vpc-acl + + ipRange: + Description: IP Range for the Givesource VPC + Value: !FindInMap [IpRange, !Ref 'AWS::Region', !Ref 'AWS::AccountId'] + Export: + Name: givesource-vpc-ip-range + + primaryPublicSubnet: + Description: Primary Public Subnet for Givesource + Value: !Ref primaryPublicSubnet + Export: + Name: givsource-primary-public-subnet + + secondaryPublicSubnet: + Description: Secondary Public Subnet for Givesource + Value: !Ref secondaryPublicSubnet + Export: + Name: givesource-secondary-public-subnet + + primaryPrivateSubnet: + Description: Primary Private Subnet for Givesource + Value: !Ref primaryPrivateSubnet + Export: + Name: givsource-primary-private-subnet + + secondaryPrivateSubnet: + Description: Secondary Private Subnet for Givesource + Value: !Ref secondaryPrivateSubnet + Export: + Name: givesource-secondary-private-subnet + diff --git a/config/default.json b/config/default.json index e1368c32..0e73e465 100644 --- a/config/default.json +++ b/config/default.json @@ -5,7 +5,8 @@ "ADMIN_PAGES_SSL_CERTIFICATE_ARN": "", "PUBLIC_PAGES_CNAMES": [], "PUBLIC_PAGES_SSL_CERTIFICATE_ARN": "", - "ENABLE_MONITORING": "" + "ENABLE_MONITORING": "", + "REPLICA_REGION": "" }, "stack": { "AWS_REGION": "", @@ -17,4 +18,4 @@ "AWS_LAMBDA_RELEASE_BUCKET_PREFIX": "", "AWS_LAMBDA_RELEASE_BUCKET_AVAILABLE_REGIONS": [] } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index ce70af44..986c87ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "givesource", - "version": "1.4.4", + "version": "2.1.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 22e36a1a..bf8d2eb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "givesource", - "version": "1.4.4", + "version": "2.1.1", "description": "Pay-as-you-go highly scalable software application that helps community foundations set up and manage a platform where they can raise funds for non-profits through event pages.", "license": "Apache-2.0", "repository": { @@ -30,6 +30,7 @@ "lambda:build": "cd packages/lambda && npm run build", "lambda:clean": "cd packages/lambda && npm run clean", "lambda:delete-test-payments": "cd packages/lambda && npm run delete-test-payments", + "lambda:delete-payments-by-transaction-ids": "cd packages/lambda && npm run delete-payments-by-transaction-ids", "lambda:deploy": "cd packages/lambda && npm run deploy", "lambda:install": "cd packages/lambda && npm install", "lambda:release": "cd packages/lambda && npm run release", diff --git a/packages/cloudformation/bin/aws/cloudFormation.js b/packages/cloudformation/bin/aws/cloudFormation.js index 414ef390..9b6c51e4 100644 --- a/packages/cloudformation/bin/aws/cloudFormation.js +++ b/packages/cloudformation/bin/aws/cloudFormation.js @@ -39,7 +39,8 @@ CloudFormation.prototype.createStack = function (region, stackName, templateUrl, const params = { Capabilities: ['CAPABILITY_IAM'], StackName: stackName, - TemplateURL: templateUrl + TemplateURL: templateUrl, + OnFailure: 'DO_NOTHING' }; if (parameters.length) { params.Parameters = parameters; @@ -104,4 +105,4 @@ CloudFormation.prototype.updateStack = function (region, stackName, templateUrl, }); }; -module.exports = CloudFormation; \ No newline at end of file +module.exports = CloudFormation; diff --git a/packages/cloudformation/bin/create.js b/packages/cloudformation/bin/create.js index 927dc5e4..e81587f7 100644 --- a/packages/cloudformation/bin/create.js +++ b/packages/cloudformation/bin/create.js @@ -42,6 +42,7 @@ const createStack = function () { PUBLIC_PAGES_CNAMES: 'PublicPagesCNAMEs', PUBLIC_PAGES_SSL_CERTIFICATE_ARN: 'PublicPagesSSLCertificateArn', ENABLE_MONITORING: 'EnableMonitoring', + REPLICA_REGION: 'ReplicaRegion' }; Object.keys(optionalParams).forEach(function (key) { if (config.app.hasOwnProperty(key) && config.app[key]) { @@ -61,4 +62,4 @@ createStack().then(function (response) { console.log('Stack create in progress: ' + response.StackId); }).catch(function (err) { console.log(err); -}); \ No newline at end of file +}); diff --git a/packages/cloudformation/bin/update.js b/packages/cloudformation/bin/update.js index 8d32bd39..80b3d7a3 100644 --- a/packages/cloudformation/bin/update.js +++ b/packages/cloudformation/bin/update.js @@ -42,6 +42,7 @@ const updateStack = function () { PUBLIC_PAGES_CNAMES: 'PublicPagesCNAMEs', PUBLIC_PAGES_SSL_CERTIFICATE_ARN: 'PublicPagesSSLCertificateArn', ENABLE_MONITORING: 'EnableMonitoring', + REPLICA_REGION: 'ReplicaRegion' }; Object.keys(optionalParams).forEach(function (key) { if (config.app.hasOwnProperty(key) && config.app[key]) { diff --git a/packages/cloudformation/templates/givesource-api-contents.yml b/packages/cloudformation/templates/givesource-api-contents.yml index 6d0321f6..95492592 100644 --- a/packages/cloudformation/templates/givesource-api-contents.yml +++ b/packages/cloudformation/templates/givesource-api-contents.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -48,10 +51,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetContents Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetContentsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -77,10 +86,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostContent Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostContentLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -106,10 +121,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchContent Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchContentLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -118,7 +139,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/contents/{content_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/contents/{content_id} DependsOn: PatchContentLambdaFunction PatchContentsLambdaFunction: @@ -135,10 +156,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchContents Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchContentsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -164,10 +191,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteContent Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteContentLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -176,7 +209,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/contents/{content_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/contents/{content_id} DependsOn: DeleteContentLambdaFunction DeleteContentsLambdaFunction: @@ -193,10 +226,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteContents Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteContentsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -222,7 +261,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref ContentsApiResource - PathPart: "{content_uuid}" + PathPart: "{content_id}" GetContentsApiMethod: Type: AWS::ApiGateway::Method @@ -725,4 +764,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-deploy.yml b/packages/cloudformation/templates/givesource-api-deploy.yml index 2558f780..22a6e5b2 100644 --- a/packages/cloudformation/templates/givesource-api-deploy.yml +++ b/packages/cloudformation/templates/givesource-api-deploy.yml @@ -7,6 +7,24 @@ Parameters: Type: String Resources: + ApiGatewayLogRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: apigateway.amazonaws.com + Action: sts:AssumeRole + Path: / + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs + + ApiGatewayAccount: + Type: AWS::ApiGateway::Account + Properties: + CloudWatchRoleArn: !GetAtt ApiGatewayLogRole.Arn ApiProdDeployment: Type: AWS::ApiGateway::Deployment @@ -44,6 +62,11 @@ Resources: CacheDataEncrypted: true CacheTtlInSeconds: 300 CachingEnabled: true + - ResourcePath: "/files/download/{file_id}" + HttpMethod: GET + LoggingLevel: INFO + DataTraceEnabled: true + CachingEnabled: false - ResourcePath: "/metrics" HttpMethod: GET CacheDataEncrypted: true @@ -64,7 +87,7 @@ Resources: CacheDataEncrypted: true CacheTtlInSeconds: 60 CachingEnabled: true - - ResourcePath: "/nonprofits/{nonprofit_uuid}" + - ResourcePath: "/nonprofits/{nonprofit_id}" HttpMethod: GET CacheDataEncrypted: true CacheTtlInSeconds: 60 @@ -79,8 +102,9 @@ Resources: CacheDataEncrypted: true CacheTtlInSeconds: 300 CachingEnabled: true - - ResourcePath: "/sponsor-tiers/{sponsor_tier_uuid}/sponsors" + - ResourcePath: "/sponsor-tiers/{sponsor_tier_id}/sponsors" HttpMethod: GET CacheDataEncrypted: true CacheTtlInSeconds: 300 - CachingEnabled: true \ No newline at end of file + CachingEnabled: true + DependsOn: ApiGatewayAccount diff --git a/packages/cloudformation/templates/givesource-api-donations.yml b/packages/cloudformation/templates/givesource-api-donations.yml index b80ef778..60d33293 100644 --- a/packages/cloudformation/templates/givesource-api-donations.yml +++ b/packages/cloudformation/templates/givesource-api-donations.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + SecureLambdaRoleArn: Type: String @@ -51,10 +54,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -63,7 +72,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/donations/{donation_id} DependsOn: GetDonationLambdaFunction GetDonationsLambdaFunction: @@ -80,10 +89,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetDonations Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetDonationsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -109,10 +124,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -138,10 +159,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -150,7 +177,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/donations/{donation_id} DependsOn: PatchDonationLambdaFunction DeleteDonationLambdaFunction: @@ -167,10 +194,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -179,7 +212,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/donations/{donation_id} DependsOn: DeleteDonationLambdaFunction # Process Donations Lambda Resources @@ -196,10 +229,16 @@ Resources: AWS_STACK_NAME: !Ref StackName FunctionName: !Sub ${StackName}-ProcessDonations Handler: "index.handle" - MemorySize: 128 + MemorySize: 1024 Role: !Ref SecureLambdaRoleArn Runtime: "nodejs12.x" - Timeout: !Ref DefaultLambdaFunctionTimeout + Timeout: 90 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet ProcessDonationsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -226,10 +265,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostDonationsReceipt Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostDonationsReceiptLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -255,10 +300,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetDonationsReceipt Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetDonationsReceiptLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -286,10 +337,16 @@ Resources: FunctionName: !Sub |- ${StackName}-AdminPostDonationsReceipt Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet AdminPostDonationsReceiptLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -315,7 +372,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref DonationsApiResource - PathPart: "{donation_uuid}" + PathPart: "{donation_id}" GetDonationApiMethod: Type: AWS::ApiGateway::Method diff --git a/packages/cloudformation/templates/givesource-api-donors.yml b/packages/cloudformation/templates/givesource-api-donors.yml index 49a502ef..a51a9720 100644 --- a/packages/cloudformation/templates/givesource-api-donors.yml +++ b/packages/cloudformation/templates/givesource-api-donors.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -48,10 +51,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetDonor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetDonorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -60,7 +69,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/donors/{donor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/donors/{donor_id} DependsOn: GetDonorLambdaFunction GetDonorsLambdaFunction: @@ -77,10 +86,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetDonors Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetDonorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -106,10 +121,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostDonor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostDonorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -135,10 +156,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteDonor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteDonorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -147,7 +174,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/donors/{donor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/donors/{donor_id} DependsOn: DeleteDonorLambdaFunction # Donors Api Gateway Resources @@ -164,7 +191,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref DonorsApiResource - PathPart: "{donor_uuid}" + PathPart: "{donor_id}" GetDonorApiMethod: Type: AWS::ApiGateway::Method @@ -514,4 +541,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-files.yml b/packages/cloudformation/templates/givesource-api-files.yml index 190d24e5..a70bfd21 100644 --- a/packages/cloudformation/templates/givesource-api-files.yml +++ b/packages/cloudformation/templates/givesource-api-files.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -30,6 +33,9 @@ Parameters: UploadsBucket: Type: String + ReportsBucket: + Type: String + AuthorizeUsers: Type: String @@ -37,6 +43,42 @@ Resources: # Files Lambda Resources + DownloadFileLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/DownloadFile.zip + Description: "Download a file by id" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET: !Ref ReportsBucket + FunctionName: !Sub |- + ${StackName}-DownloadFile + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + DownloadLambdaInvokePermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !GetAtt DownloadFileLambdaFunction.Arn + Action: "lambda:InvokeFunction" + Principal: "apigateway.amazonaws.com" + SourceArn: !Sub |- + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/files/download/{file_id} + DependsOn: DownloadFileLambdaFunction + GetFileLambdaFunction: Type: AWS::Lambda::Function Properties: @@ -51,10 +93,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetFile Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetFileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -63,7 +111,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/files/{file_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/files/{file_id} DependsOn: GetFileLambdaFunction GetFilesLambdaFunction: @@ -80,10 +128,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetFiles Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetFilesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -110,10 +164,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostFile Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostFileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -140,10 +200,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteFile Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteFileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -152,7 +218,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/files/{file_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/files/{file_id} DependsOn: DeleteFileLambdaFunction DeleteFilesLambdaFunction: @@ -170,10 +236,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteFiles Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteFilesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -199,7 +271,96 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref FilesApiResource - PathPart: "{file_uuid}" + PathPart: "{file_id}" + + FileDownloadApiResource: + Type: AWS::ApiGateway::Resource + Properties: + RestApiId: !Ref RestApi + ParentId: !Ref FilesApiResource + PathPart: "download" + + FileDownloadFileApiResource: + Type: AWS::ApiGateway::Resource + Properties: + RestApiId: !Ref RestApi + ParentId: !Ref FileDownloadApiResource + PathPart: "{file_id}" + + FileDownloadApiMethod: + Type: AWS::ApiGateway::Method + Properties: + RestApiId: !Ref RestApi + ResourceId: !Ref FileDownloadFileApiResource + HttpMethod: GET + AuthorizationType: CUSTOM + AuthorizerId: !Ref AuthorizeUsers + ApiKeyRequired: false + RequestParameters: + method.request.header.Authorization: true + Integration: + Type: AWS + IntegrationHttpMethod: POST + PassthroughBehavior: NEVER + RequestTemplates: + application/json: !Ref IntegrationRequestTemplate + Uri: !Sub + - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function}/invocations + - Function: !GetAtt DownloadFileLambdaFunction.Arn + IntegrationResponses: + - StatusCode: 200 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: "'*'" + - StatusCode: 400 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: "'*'" + SelectionPattern: .*"httpStatus":400.* + ResponseTemplates: + application/json: !Ref IntegrationResponsesTemplate + - StatusCode: 401 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: "'*'" + SelectionPattern: .*"httpStatus":401.* + ResponseTemplates: + application/json: !Ref IntegrationResponsesTemplate + - StatusCode: 403 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: "'*'" + SelectionPattern: .*"httpStatus":403.* + ResponseTemplates: + application/json: !Ref IntegrationResponsesTemplate + - StatusCode: 404 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: "'*'" + SelectionPattern: .*"httpStatus":404.* + ResponseTemplates: + application/json: !Ref IntegrationResponsesTemplate + - StatusCode: 500 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: "'*'" + SelectionPattern: .*"httpStatus":500.* + ResponseTemplates: + application/json: !Ref IntegrationResponsesTemplate + MethodResponses: + - StatusCode: 200 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: true + - StatusCode: 400 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: true + - StatusCode: 401 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: true + - StatusCode: 403 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: true + - StatusCode: 404 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: true + - StatusCode: 500 + ResponseParameters: + method.response.header.Access-Control-Allow-Origin: true + DependsOn: DownloadFileLambdaFunction GetFileApiMethod: Type: AWS::ApiGateway::Method @@ -283,14 +444,14 @@ Resources: ApiKeyRequired: false RequestParameters: method.request.querystring.c: false - method.request.querystring.uuids: true + method.request.querystring.fileIds: true Integration: Type: AWS IntegrationHttpMethod: POST PassthroughBehavior: NEVER CacheKeyParameters: - method.request.querystring.c - - method.request.querystring.uuids + - method.request.querystring.fileIds RequestTemplates: application/json: !Ref IntegrationRequestTemplate Uri: !Sub @@ -624,4 +785,29 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true + + OptionsFileDownloadApiMethod: + Type: AWS::ApiGateway::Method + Properties: + RestApiId: !Ref RestApi + ResourceId: !Ref FileDownloadFileApiResource + HttpMethod: OPTIONS + AuthorizationType: NONE + ApiKeyRequired: false + Integration: + Type: MOCK + RequestTemplates: + application/json: !Ref SuccessResponseTemplate + IntegrationResponses: + - StatusCode: 200 + ResponseParameters: + method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Requested-With,X-Requested-By,X-Api-Key'" + method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'" + method.response.header.Access-Control-Allow-Origin: "'*'" + MethodResponses: + - StatusCode: 200 + ResponseParameters: + method.response.header.Access-Control-Allow-Headers: true + method.response.header.Access-Control-Allow-Methods: true + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-messages.yml b/packages/cloudformation/templates/givesource-api-messages.yml index 8627af0b..63c7ef0a 100644 --- a/packages/cloudformation/templates/givesource-api-messages.yml +++ b/packages/cloudformation/templates/givesource-api-messages.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -48,10 +51,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetMessage Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetMessageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -60,7 +69,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/messages/{message_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/messages/{message_id} DependsOn: GetMessageLambdaFunction GetMessagesLambdaFunction: @@ -77,10 +86,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetMessages Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetMessagesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -106,10 +121,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostMessage Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostMessageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -135,10 +156,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchMessage Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchMessageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -147,7 +174,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/messages/{message_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/messages/{message_id} DependsOn: PatchMessageLambdaFunction DeleteMessageLambdaFunction: @@ -164,10 +191,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteMessage Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteMessageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -176,7 +209,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/messages/{message_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/messages/{message_id} DependsOn: DeleteMessageLambdaFunction # Messages Api Gateway Resources @@ -193,7 +226,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref MessagesApiResource - PathPart: "{message_uuid}" + PathPart: "{message_id}" GetMessageApiMethod: Type: AWS::ApiGateway::Method @@ -615,4 +648,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-metrics.yml b/packages/cloudformation/templates/givesource-api-metrics.yml index c87af4a5..512fa315 100644 --- a/packages/cloudformation/templates/givesource-api-metrics.yml +++ b/packages/cloudformation/templates/givesource-api-metrics.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -48,10 +51,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetMetrics Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetMetricsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -77,7 +86,7 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchMetrics Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -106,7 +115,7 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteMetrics Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -381,4 +390,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-nonprofits.yml b/packages/cloudformation/templates/givesource-api-nonprofits.yml index c6a3e7df..26290aad 100644 --- a/packages/cloudformation/templates/givesource-api-nonprofits.yml +++ b/packages/cloudformation/templates/givesource-api-nonprofits.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -47,17 +50,23 @@ Resources: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} S3Key: fn/{{version}}/GetNonprofit.zip - Description: "Get a nonprofit by uuid" + Description: "Get a nonprofit by id" Environment: Variables: AWS_STACK_NAME: !Ref StackName FunctionName: !Sub |- ${StackName}-GetNonprofit Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -66,7 +75,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id} DependsOn: GetNonprofitLambdaFunction GetNonprofitsLambdaFunction: @@ -83,10 +92,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofits Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -112,10 +127,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostNonprofit Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -141,10 +162,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchNonprofit Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -153,7 +180,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id} DependsOn: PatchNonprofitLambdaFunction DeleteNonprofitLambdaFunction: @@ -170,10 +197,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteNonprofit Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -182,7 +215,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id} DependsOn: DeleteNonprofitLambdaFunction # Nonprofit Donations Lambda Resources @@ -194,17 +227,23 @@ Resources: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} S3Key: fn/{{version}}/GetNonprofitDonation.zip - Description: "Get a nonprofit's donation by uuid" + Description: "Get a nonprofit's donation by id" Environment: Variables: AWS_STACK_NAME: !Ref StackName FunctionName: !Sub |- ${StackName}-GetNonprofitDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -213,7 +252,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/donations/{donation_id} DependsOn: GetNonprofitDonationLambdaFunction GetNonprofitDonationsLambdaFunction: @@ -230,10 +269,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitDonations Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -242,7 +287,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/donations + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/donations DependsOn: GetNonprofitDonationsLambdaFunction PostNonprofitDonationLambdaFunction: @@ -259,10 +304,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostNonprofitDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -271,7 +322,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/donations + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/donations DependsOn: PostNonprofitDonationLambdaFunction PatchNonprofitDonationLambdaFunction: @@ -288,10 +339,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchNonprofitDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -300,7 +357,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/donations/{donation_id} DependsOn: PatchNonprofitDonationLambdaFunction DeleteNonprofitDonationLambdaFunction: @@ -317,10 +374,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteNonprofitDonation Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitDonationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -329,7 +392,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/donations/{donation_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/donations/{donation_id} DependsOn: DeleteNonprofitDonationLambdaFunction # Nonprofit Donation Tiers Lambda Resources @@ -348,10 +411,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitDonationTier Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -360,7 +429,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/tiers/{donation_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/tiers/{donation_tier_id} DependsOn: GetNonprofitDonationTierLambdaFunction GetNonprofitDonationTiersLambdaFunction: @@ -377,10 +446,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitDonationTiers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitDonationTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -389,7 +464,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/tiers DependsOn: GetNonprofitDonationTiersLambdaFunction PostNonprofitDonationTierLambdaFunction: @@ -406,10 +481,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostNonprofitDonationTier Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitDonationTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -418,7 +499,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/tiers DependsOn: PostNonprofitDonationTierLambdaFunction PatchNonprofitDonationTiersLambdaFunction: @@ -435,10 +516,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchNonprofitDonationTiers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitDonationTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -447,7 +534,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/tiers DependsOn: PatchNonprofitDonationTiersLambdaFunction DeleteNonprofitDonationTiersLambdaFunction: @@ -464,10 +551,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteNonprofitDonationTiers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitDonationTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -476,7 +569,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/tiers + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/tiers DependsOn: DeleteNonprofitDonationTiersLambdaFunction # Nonprofit Pages Lambda Resources @@ -488,17 +581,23 @@ Resources: S3Bucket: !Sub |- {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} S3Key: fn/{{version}}/GetNonprofitPage.zip - Description: "Get a nonprofit by uuid" + Description: "Get a nonprofit by id" Environment: Variables: AWS_STACK_NAME: !Ref StackName FunctionName: !Sub |- ${StackName}-GetNonprofitPage Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: 30 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitPageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -526,10 +625,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitReport Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitReportLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -538,7 +643,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/reports/{report_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/reports/{report_id} DependsOn: GetNonprofitReportLambdaFunction PostNonprofitReportLambdaFunction: @@ -555,10 +660,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostNonprofitReport Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitReportLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -567,7 +678,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/reports + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/reports DependsOn: PostNonprofitReportLambdaFunction # Nonprofit Slides Lambda Resources @@ -586,10 +697,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitSlide Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -598,7 +715,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/slides/{slide_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/slides/{slide_id} DependsOn: GetNonprofitSlideLambdaFunction GetNonprofitSlidesLambdaFunction: @@ -615,10 +732,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitSlides Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitSlidesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -627,7 +750,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/slides + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/slides DependsOn: GetNonprofitSlidesLambdaFunction PostNonprofitSlideLambdaFunction: @@ -644,10 +767,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostNonprofitSlide Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -656,7 +785,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/slides + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/slides DependsOn: PostNonprofitSlideLambdaFunction PatchNonprofitSlideLambdaFunction: @@ -673,10 +802,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchNonprofitSlide Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -685,7 +820,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/slides/{slide_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/slides/{slide_id} DependsOn: PatchNonprofitSlideLambdaFunction PatchNonprofitSlidesLambdaFunction: @@ -702,10 +837,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchNonprofitSlides Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitSlidesLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -714,7 +855,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/slides + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/slides DependsOn: PatchNonprofitSlidesLambdaFunction DeleteNonprofitSlideLambdaFunction: @@ -732,10 +873,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteNonprofitSlide Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitSlideLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -744,7 +891,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/slides/{slide_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/slides/{slide_id} DependsOn: PatchNonprofitSlideLambdaFunction # Nonprofit Users Lambda Resources @@ -763,10 +910,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetNonprofitUsers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetNonprofitUsersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -775,7 +928,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_uuid}/users + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/nonprofits/{nonprofit_id}/users DependsOn: GetNonprofitUsersLambdaFunction PostNonprofitUserLambdaFunction: @@ -793,10 +946,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostNonprofitUser Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostNonprofitUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -805,7 +964,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_uuid}/users + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/nonprofits/{nonprofit_id}/users DependsOn: PostNonprofitUserLambdaFunction DeleteNonprofitUserLambdaFunction: @@ -823,10 +982,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteNonprofitUser Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteNonprofitUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -835,7 +1000,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_uuid}/users/{user_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/nonprofits/{nonprofit_id}/users/{user_id} DependsOn: DeleteNonprofitUserLambdaFunction # Nonprofit Admin Lambda Resources @@ -855,10 +1020,16 @@ Resources: FunctionName: !Sub |- ${StackName}-AdminRegisterNonprofit Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet NonprofitAdminRegisterLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -886,10 +1057,16 @@ Resources: FunctionName: !Sub |- ${StackName}-RegisterNonprofit Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet NonprofitRegisterLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -917,10 +1094,16 @@ Resources: FunctionName: !Sub |- ${StackName}-SearchNonprofits Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet SearchNonprofitsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -949,10 +1132,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchNonprofitStatus Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchNonprofitStatusLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -961,7 +1150,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_uuid}/status + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/nonprofits/{nonprofit_id}/status DependsOn: PatchNonprofitStatusLambdaFunction # Nonprofits Api Gateway Resources @@ -978,7 +1167,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitsApiResource - PathPart: "{nonprofit_uuid}" + PathPart: "{nonprofit_id}" GetNonprofitApiMethod: Type: AWS::ApiGateway::Method @@ -990,14 +1179,14 @@ Resources: ApiKeyRequired: false RequestParameters: method.request.querystring.c: false - method.request.path.nonprofit_uuid: true + method.request.path.nonprofit_id: true Integration: Type: AWS IntegrationHttpMethod: POST PassthroughBehavior: NEVER CacheKeyParameters: - method.request.querystring.c - - method.request.path.nonprofit_uuid + - method.request.path.nonprofit_id RequestTemplates: application/json: !Ref IntegrationRequestTemplate Uri: !Sub @@ -1431,7 +1620,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitDonationsApiResource - PathPart: "{donation_uuid}" + PathPart: "{donation_id}" GetNonprofitDonationApiMethod: Type: AWS::ApiGateway::Method @@ -1875,7 +2064,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitDonationTiersApiResource - PathPart: "{donation_tier_uuid}" + PathPart: "{donation_tier_id}" GetNonprofitDonationTierApiMethod: Type: AWS::ApiGateway::Method @@ -2427,7 +2616,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NoprofitReportsApiResource - PathPart: "{report_uuid}" + PathPart: "{report_id}" GetNonprofitReportApiMethod: Type: AWS::ApiGateway::Method @@ -2643,7 +2832,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitSlidesApiResource - PathPart: "{slide_uuid}" + PathPart: "{slide_id}" GetNonprofitSlideApiMethod: Type: AWS::ApiGateway::Method @@ -3153,7 +3342,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref NonprofitUsersApiResource - PathPart: "{user_uuid}" + PathPart: "{user_id}" GetNonprofitUsersApiMethod: Type: AWS::ApiGateway::Method @@ -3875,4 +4064,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-payment-transactions.yml b/packages/cloudformation/templates/givesource-api-payment-transactions.yml index 2236074c..8b3a5886 100644 --- a/packages/cloudformation/templates/givesource-api-payment-transactions.yml +++ b/packages/cloudformation/templates/givesource-api-payment-transactions.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -48,10 +51,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetPaymentTransaction Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetPaymentTransactionLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -60,7 +69,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/paymentTransactions/{payment_transaction_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/paymentTransactions/{payment_transaction_id} DependsOn: GetPaymentTransactionLambdaFunction GetPaymentTransactionsLambdaFunction: @@ -77,10 +86,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetPaymentTransactions Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetPaymentTransactionsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -106,10 +121,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostPaymentTransaction Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostPaymentTransactionLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -135,10 +156,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchPaymentTransaction Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchPaymentTransactionLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -147,7 +174,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/paymentTransactions/{payment_transaction_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/paymentTransactions/{payment_transaction_id} DependsOn: PatchPaymentTransactionLambdaFunction DeletePaymentTransactionLambdaFunction: @@ -164,10 +191,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeletePaymentTransaction Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeletePaymentTransactionLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -176,7 +209,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/paymentTransactions/{payment_transaction_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/paymentTransactions/{payment_transaction_id} DependsOn: DeletePaymentTransactionLambdaFunction # Payment Transactions Api Gateway Resources @@ -193,7 +226,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref PaymentTransactionsApiResource - PathPart: "{paymen_transaction_uuid}" + PathPart: "{payment_transaction_id}" GetPaymentTransactionApiMethod: Type: AWS::ApiGateway::Method @@ -618,4 +651,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-reports.yml b/packages/cloudformation/templates/givesource-api-reports.yml index b496d95e..209e1b30 100644 --- a/packages/cloudformation/templates/givesource-api-reports.yml +++ b/packages/cloudformation/templates/givesource-api-reports.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -51,10 +54,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetReport Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetReportLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -63,7 +72,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/reports/{report_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/reports/{report_id} DependsOn: GetReportLambdaFunction PostReportLambdaFunction: @@ -80,10 +89,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostReport Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostReportLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -109,7 +124,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref ReportsApiResource - PathPart: "{report_uuid}" + PathPart: "{report_id}" GetReportApiMethod: Type: AWS::ApiGateway::Method @@ -309,4 +324,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-settings.yml b/packages/cloudformation/templates/givesource-api-settings.yml index c15a2936..eb7bd015 100644 --- a/packages/cloudformation/templates/givesource-api-settings.yml +++ b/packages/cloudformation/templates/givesource-api-settings.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -63,10 +66,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSetting Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -92,10 +101,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSettings Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -121,10 +136,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostSetting Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -150,10 +171,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSetting Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -179,10 +206,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSettings Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -208,10 +241,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteSetting Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -237,10 +276,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteSettings Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSettingsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -268,7 +313,7 @@ Resources: FunctionName: !Sub |- ${StackName}-GetEmail Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -298,7 +343,7 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSenderEmailAddress Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -331,7 +376,7 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSenderEmailAddress Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -360,7 +405,7 @@ Resources: FunctionName: !Sub |- ${StackName}-VerifyEmail Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -389,10 +434,16 @@ Resources: AWS_STACK_NAME: !Ref StackName FunctionName: !Sub ${StackName}-GetSecureSetting Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref SecureSettingsLambdaFunctionRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSecureSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -416,10 +467,16 @@ Resources: KMS_KEY: !Ref SecureSettingsKeyAlias FunctionName: !Sub ${StackName}-PatchSecureSetting Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref SecureSettingsLambdaFunctionRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSecureSettingLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -1608,4 +1665,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-sponsors.yml b/packages/cloudformation/templates/givesource-api-sponsors.yml index 4f797ce9..93c3d34a 100644 --- a/packages/cloudformation/templates/givesource-api-sponsors.yml +++ b/packages/cloudformation/templates/givesource-api-sponsors.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -48,10 +51,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSponsorTier Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -60,7 +69,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_id} DependsOn: GetSponsorTierLambdaFunction GetSponsorTiersLambdaFunction: @@ -77,10 +86,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSponsorTiers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -106,10 +121,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostSponsorTier Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSponsorTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -135,10 +156,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSponsorTier Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -147,7 +174,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_id} DependsOn: PatchSponsorTierLambdaFunction PatchSponsorTiersLambdaFunction: @@ -164,10 +191,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSponsorTiers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorTiersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -193,10 +226,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteSponsorTier Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSponsorTierLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -205,7 +244,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_id} DependsOn: DeleteSponsorTierLambdaFunction # Sponsors Lambda Resources @@ -224,10 +263,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSponsor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -236,7 +281,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_uuid}/sponsors/{sponsor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_id}/sponsors/{sponsor_id} DependsOn: GetSponsorLambdaFunction GetSponsorsLambdaFunction: @@ -253,10 +298,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetSponsors Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetSponsorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -265,7 +316,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/GET/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: GetSponsorsLambdaFunction PostSponsorLambdaFunction: @@ -282,10 +333,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostSponsor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -294,7 +351,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: PostSponsorLambdaFunction PatchSponsorLambdaFunction: @@ -311,10 +368,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSponsor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -323,7 +386,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_uuid}/sponsors/{sponsor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_id}/sponsors/{sponsor_id} DependsOn: PatchSponsorLambdaFunction PatchSponsorsLambdaFunction: @@ -340,10 +403,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchSponsors Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchSponsorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -352,7 +421,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: PatchSponsorsLambdaFunction DeleteSponsorLambdaFunction: @@ -369,10 +438,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteSponsor Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSponsorLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -381,7 +456,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_uuid}/sponsors/{sponsor_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_id}/sponsors/{sponsor_id} DependsOn: DeleteSponsorLambdaFunction DeleteSponsorsLambdaFunction: @@ -398,10 +473,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteSponsors Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteSponsorsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -410,7 +491,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_uuid}/sponsors + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/sponsor-tiers/{sponsor_tier_id}/sponsors DependsOn: DeleteSponsorsLambdaFunction # Sponsor Tiers Api Gateway Resources @@ -427,7 +508,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref SponsorTiersApiResource - PathPart: "{sponsor_tier_uuid}" + PathPart: "{sponsor_tier_id}" GetSponsorTierApiMethod: Type: AWS::ApiGateway::Method @@ -941,7 +1022,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref SponsorsApiResource - PathPart: "{sponsor_uuid}" + PathPart: "{sponsor_id}" GetSponsorApiMethod: Type: AWS::ApiGateway::Method @@ -1025,14 +1106,14 @@ Resources: ApiKeyRequired: false RequestParameters: method.request.querystring.c: false - method.request.path.sponsor_tier_uuid: true + method.request.path.sponsor_tier_id: true Integration: Type: AWS IntegrationHttpMethod: POST PassthroughBehavior: NEVER CacheKeyParameters: - method.request.querystring.c - - method.request.path.sponsor_tier_uuid + - method.request.path.sponsor_tier_id RequestTemplates: application/json: !Ref IntegrationRequestTemplate Uri: !Sub @@ -1516,4 +1597,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-api-users.yml b/packages/cloudformation/templates/givesource-api-users.yml index 3168ff49..2732e33d 100644 --- a/packages/cloudformation/templates/givesource-api-users.yml +++ b/packages/cloudformation/templates/givesource-api-users.yml @@ -9,6 +9,9 @@ Parameters: LambdaRoleArn: Type: String + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -51,10 +54,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetUserProfile Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetUserProfileLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -83,10 +92,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GetUsers Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet GetUsersLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -113,10 +128,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PostUser Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: 30 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PostUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -142,10 +163,16 @@ Resources: FunctionName: !Sub |- ${StackName}-PatchUser Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet PatchUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -154,7 +181,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/users/{user_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/PATCH/users/{user_id} DependsOn: PatchUserLambdaFunction DeleteUserLambdaFunction: @@ -172,10 +199,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteUser Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteUserLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -184,7 +217,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/users/{user_uuid} + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/DELETE/users/{user_id} DependsOn: DeleteUserLambdaFunction # Resend User Email Verification Lambda Resources @@ -204,10 +237,16 @@ Resources: FunctionName: !Sub |- ${StackName}-ResendUserEmailVerification Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: 30 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet ResendUserEmailVerificationLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -216,7 +255,7 @@ Resources: Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub |- - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/users/{user_uuid}/resend-verification-email + arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/users/{user_id}/resend-verification-email DependsOn: ResendUserEmailVerificationLambdaFunction # User Profile Api Gateway Resources @@ -342,7 +381,7 @@ Resources: Properties: RestApiId: !Ref RestApi ParentId: !Ref UsersApiResource - PathPart: "{user_uuid}" + PathPart: "{user_id}" GetUsersApiMethod: Type: AWS::ApiGateway::Method @@ -801,4 +840,4 @@ Resources: ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true - method.response.header.Access-Control-Allow-Origin: true \ No newline at end of file + method.response.header.Access-Control-Allow-Origin: true diff --git a/packages/cloudformation/templates/givesource-aurora-snapshot-copy.yml b/packages/cloudformation/templates/givesource-aurora-snapshot-copy.yml new file mode 100644 index 00000000..d683aa69 --- /dev/null +++ b/packages/cloudformation/templates/givesource-aurora-snapshot-copy.yml @@ -0,0 +1,280 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: Copies AWS Aurora snapshot to the DR region for Givesource(R) +Parameters: + StackName: + Type: String + SourceRegion: + Type: String + Default: us-east-1 + DestinationRegion: + Type: String + Default: us-west-2 +Resources: + SnapshotCopyFunctionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Policies: + - PolicyName: kms-read + PolicyDocument: + Statement: + - Effect: Allow + Action: + - kms:DescribeKey + Resource: + - '*' + - PolicyName: rds-read + PolicyDocument: + Statement: + - Effect: Allow + Action: + - rds:DescribeDbClusters + - rds:DescribeDbClusterSnapshots + Resource: + - '*' + - PolicyName: rds-snapshot-modify + PolicyDocument: + Statement: + - Effect: Allow + Action: + - rds:AddTagsToResource + - rds:CopyDBClusterSnapshot + Resource: + - !Sub 'arn:aws:rds:${SourceRegion}:${AWS::AccountId}:cluster-snapshot:*' + - !Sub 'arn:aws:rds:${DestinationRegion}:${AWS::AccountId}:cluster-snapshot:*' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + SnapshotCopyFunction: + Type: AWS::Lambda::Function + Properties: + Code: + ZipFile: | + const { RDS, KMS } = require('aws-sdk'); + exports.handler = async (event, context, callback) => { + const clusterPrefix = process.env.CLUSTER_PREFIX.toLowerCase(); + const sourceRegion = process.env.SOURCE_REGION; + const destinationRegion = process.env.DESTINATION_REGION; + + const sourceRds = new RDS({region: sourceRegion}); + const destinationRds = new RDS({region: destinationRegion}); + const destinationKms = new KMS({region: destinationRegion}); + + // encrypt with the default rds key + var { KeyMetadata } = await destinationKms.describeKey({KeyId: 'alias/aws/rds'}).promise(); + let destinationRdsDefaultKeyId = KeyMetadata.KeyId; + + // find the db cluster which starts with our name + var { DBClusters } = await sourceRds.describeDBClusters().promise(); + var clusterIdentifier = DBClusters.find(it => it['DBClusterIdentifier'].startsWith(clusterPrefix))['DBClusterIdentifier']; + + // search for all automated snapshots for this cluster + let params = { + DBClusterIdentifier: clusterIdentifier, + SnapshotType: 'automated' + }; + const { DBClusterSnapshots } = await sourceRds.describeDBClusterSnapshots(params).promise(); + + // iterate over all snapshots and copy any which aren't in the dest region + DBClusterSnapshots.forEach(async function(item) { + console.log(`Processing ${item.DBClusterSnapshotIdentifier}`); + + // Add a snapshot creation tag if not present (to make deleting easier) + let dateTagKey = 'SnapshotCreateTime'; + let dateTag = item.TagList.find(tag => tag['Key'] == dateTagKey); + if (!dateTag) { + console.log(`Tagging with ${dateTagKey}`); + let params = { + ResourceName: item.DBClusterSnapshotArn, + Tags: [ + { + Key: dateTagKey, + Value: item.SnapshotCreateTime.toISOString() + } + ] + }; + await sourceRds.addTagsToResource(params).promise(); + }; + + // Copy the snapshot if it's not already marked as copied + let copyTagKey = `CopiedTo:${destinationRegion}`; + let copyTag = item.TagList.find(tag => tag['Key'] == copyTagKey); + if (!copyTag) { + console.log(`Starting copy of to ${destinationRegion}`); + let copyParams = { + SourceDBClusterSnapshotIdentifier: item.DBClusterSnapshotArn, + TargetDBClusterSnapshotIdentifier: `copy-${item.DBClusterSnapshotIdentifier.split(':')[1]}`, + CopyTags: true, + SourceRegion: sourceRegion, + KmsKeyId: destinationRdsDefaultKeyId + }; + await destinationRds.copyDBClusterSnapshot(copyParams).promise(); + + // Add a tag keeping track of images we have copied + console.log(`Tagging ${copyTagKey}`); + let tagParams = { + ResourceName: item.DBClusterSnapshotArn, + Tags: [ + { + Key: copyTagKey, + Value: new Date().toISOString() + } + ] + }; + await sourceRds.addTagsToResource(tagParams).promise(); + }; + }); + + callback(null); + }; + Description: Copies all automated snapshots to the DR Region + Environment: + Variables: + SOURCE_REGION: !Ref SourceRegion + DESTINATION_REGION: !Ref DestinationRegion + CLUSTER_PREFIX: !Sub "${StackName}-auroradbstack-" + MemorySize: 1024 + Handler: index.handler + Role: !GetAtt SnapshotCopyFunctionRole.Arn + Timeout: 30 + Runtime: nodejs12.x + SnapshotCopyFunctionLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub /aws/lambda/${SnapshotCopyFunction} + RetentionInDays: 365 + SnapshotCopyRule: + Type: AWS::Events::Rule + Properties: + Description: The cloudwatch event which copies any new snapshots to the DR every day + ScheduleExpression: rate(1 day) + State: ENABLED + Targets: + - Id: start-snapshot-copy-trigger + Arn: !GetAtt SnapshotCopyFunction.Arn + SnapshotCopyTriggerPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !GetAtt SnapshotCopyFunction.Arn + Action: lambda:InvokeFunction + Principal: events.amazonaws.com + SourceArn: !GetAtt SnapshotCopyRule.Arn + SnapshotCleanupFunctionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Policies: + - PolicyName: rds-read + PolicyDocument: + Statement: + - Effect: Allow + Action: + - rds:DescribeDbClusters + - rds:DescribeDbClusterSnapshots + Resource: + - '*' + - PolicyName: rds-snapshot-modify + PolicyDocument: + Statement: + - Effect: Allow + Action: + - rds:DeleteDBClusterSnapshot + Resource: + - !Sub 'arn:aws:rds:${DestinationRegion}:${AWS::AccountId}:cluster-snapshot:*' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + SnapshotCleanupFunction: + Type: AWS::Lambda::Function + Properties: + Code: + ZipFile: | + const { RDS } = require('aws-sdk'); + exports.handler = async (event, context, callback) => { + const clusterPrefix = process.env.CLUSTER_PREFIX.toLowerCase(); + const sourceRegion = process.env.SOURCE_REGION; + const destinationRegion = process.env.DESTINATION_REGION; + const sourceRds = new RDS({region: sourceRegion}); + const destinationRds = new RDS({region: destinationRegion}); + const maxAgeDate = new Date(new Date().setDate(new Date().getDate() - 30)); + + // find the db cluster which starts with our name + var { DBClusters } = await sourceRds.describeDBClusters().promise(); + var clusterIdentifier = DBClusters.find(it => it['DBClusterIdentifier'].startsWith(clusterPrefix))['DBClusterIdentifier']; + + // search for all manual (copied) snapshots for this cluster + let params = { + DBClusterIdentifier: clusterIdentifier, + SnapshotType: 'manual' + }; + const { DBClusterSnapshots } = await destinationRds.describeDBClusterSnapshots(params).promise(); + + // iterate over all snapshots and delete any which are over 30 days old + DBClusterSnapshots.forEach(async function(item) { + console.log(`Processing ${item.DBClusterSnapshotIdentifier}`); + + // Add a snapshot creation tag if not present (to make deleting easier) + let dateTagKey = 'SnapshotCreateTime'; + let dateTag = item.TagList.find(tag => tag['Key'] == dateTagKey); + if (dateTag) { + let snapshotCreateTime = dateTag['Value']; + if (Date.parse(snapshotCreateTime) < maxAgeDate) + { + console.log(`Snapshot create tag ${snapshotCreateTime} is more than 30 days in the past. Removing ${item.DBClusterSnapshotIdentifier}`); + let params = { + DBClusterSnapshotIdentifier: item.DBClusterSnapshotIdentifier + }; + await destinationRds.deleteDBClusterSnapshot(params).promise(); + } else { + console.log(`Snapshot create tag ${snapshotCreateTime} is less than 30 days in the past.`); + } + }; + }); + + callback(null); + }; + Description: Deletes any copied DR snapshots which are older than 30 days + Environment: + Variables: + SOURCE_REGION: !Ref SourceRegion + DESTINATION_REGION: !Ref DestinationRegion + CLUSTER_PREFIX: !Sub "${StackName}-auroradbstack-" + MemorySize: 1024 + Handler: index.handler + Role: !GetAtt SnapshotCleanupFunctionRole.Arn + Timeout: 30 + Runtime: nodejs12.x + SnapshotCleanupFunctionLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub /aws/lambda/${SnapshotCleanupFunction} + RetentionInDays: 365 + SnapshotCleanupRule: + Type: AWS::Events::Rule + Properties: + Description: The cloudwatch event which copies any new snapshots to the DR every day + ScheduleExpression: rate(1 day) + State: ENABLED + Targets: + - Id: start-snapshot-cleanup-trigger + Arn: !GetAtt SnapshotCleanupFunction.Arn + SnapshotCleanupTriggerPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !GetAtt SnapshotCleanupFunction.Arn + Action: lambda:InvokeFunction + Principal: events.amazonaws.com + SourceArn: !GetAtt SnapshotCleanupRule.Arn diff --git a/packages/cloudformation/templates/givesource-aurora.yml b/packages/cloudformation/templates/givesource-aurora.yml new file mode 100644 index 00000000..8704ce46 --- /dev/null +++ b/packages/cloudformation/templates/givesource-aurora.yml @@ -0,0 +1,350 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: AWS Aurora resources for Givesource(R) +Parameters: + DatabaseAdminUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database admin account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: admin + DatabaseMaintenanceUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database maintenance account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: maintenance + DatabaseReadwriteUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database readwrite account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: readwrite + DatabaseReadonlyUser: + AllowedPattern: "[a-zA-Z0-9_]+" + ConstraintDescription: must be between 1 to 16 alphanumeric characters. + Description: The database readonly account user name, between 1 to 16 alphanumeric characters. + MaxLength: '16' + MinLength: '1' + Type: String + Default: readonly + DatabaseName: + Type: String + Default: givesource + StackName: + Type: String + LambdaRole: + Type: String + SecureLambdaRole: + Type: String + LambdaSecurityGroupId: + Type: String + LogDatabaseDebug: + Type: String + Default: false + AllowedValues: + - true + - false + AutoPause: + Type: String + Default: false + AllowedValues: + - true + - false +Conditions: + ShouldLogDatabaseDebug: !Equals [!Ref LogDatabaseDebug, 'true'] +Resources: + DBSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Ingress/egress rules for aurora + VpcId: !ImportValue givesource-vpc + SecurityGroupIngress: [] + SecurityGroupEgress: [] + Tags: + - Key: Name + Value: givesource-aurora + DBSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: CloudFormation managed DB subnet group. + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + AdminUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${StackName}/AdminUserSecret + Description: Givesource database auto-generated admin user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseAdminUser}", "database": "${DatabaseName}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + AdminUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref AdminUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + MaintenanceUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${StackName}/MaintenanceUserSecret + Description: Givesource database auto-generated maintenance user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseMaintenanceUser}", "database": "${DatabaseName}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + MaintenanceUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref MaintenanceUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + ReadwriteUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${StackName}/ReadwriteUserSecret + Description: Givesource database auto-generated readwrite user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseReadwriteUser}", "database": "${DatabaseName}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + ReadwriteUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref ReadwriteUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + SecretsManagerPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: readwrite_user_secret_get + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref ReadwriteUserSecret + Roles: + - !Ref LambdaRole + - !Ref SecureLambdaRole + ReadonlyUserSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: !Sub ${StackName}/ReadonlyUserSecret + Description: Givesource database auto-generated readonly user password + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseReadonlyUser}", "database": "${DatabaseName}"}' + GenerateStringKey: password + PasswordLength: 32 + ExcludeCharacters: '"@/\' + ReadonlyUserSecretAttachment: + Type: AWS::SecretsManager::SecretTargetAttachment + Properties: + SecretId: !Ref ReadonlyUserSecret + TargetId: !Ref RDSCluster + TargetType: AWS::RDS::DBCluster + SecretsManagerPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: readonly_user_secret_get + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref ReadonlyUserSecret + Roles: + - !Ref LambdaRole + - !Ref SecureLambdaRole + DBClusterParameterGroup: + Type: AWS::RDS::DBClusterParameterGroup + Properties: + Description: Parameter group for RDS + Family: aurora-mysql5.7 + Parameters: + general_log: !If [ShouldLogDatabaseDebug, 1, 0] + slow_query_log: 1 + log_queries_not_using_indexes: !If [ShouldLogDatabaseDebug, 1, 0] + log_warnings: !If [ShouldLogDatabaseDebug, 1, 0] + server_audit_logging: !If [ShouldLogDatabaseDebug, 1, 0] + server_audit_logs_upload: !If [ShouldLogDatabaseDebug, 1, 0] + server_audit_events: !If [ShouldLogDatabaseDebug, 'CONNECT,QUERY,QUERY_DCL,QUERY_DDL,QUERY_DML,TABLE', !Ref AWS::NoValue] + RDSCluster: + Type: AWS::RDS::DBCluster + Properties: + BackupRetentionPeriod: 30 + DBClusterParameterGroupName: !Ref DBClusterParameterGroup + DBSubnetGroupName: !Ref DBSubnetGroup + Engine: aurora-mysql + EngineMode: serverless + EngineVersion: 5.7.mysql_aurora.2.07.1 + EnableHttpEndpoint: true +{{=<% %>=}} + MasterUsername: !Sub '{{resolve:secretsmanager:${AdminUserSecret}:SecretString:username}}' + MasterUserPassword: !Sub '{{resolve:secretsmanager:${AdminUserSecret}:SecretString:password}}' +<%={{ }}=%> + ScalingConfiguration: + AutoPause: !Ref AutoPause + MaxCapacity: 16 + MinCapacity: 1 + SecondsUntilAutoPause: 1800 + VpcSecurityGroupIds: + - !GetAtt DBSecurityGroup.GroupId + DependsOn: AdminUserSecret + LambdaAuroraIngress: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: allows access from lambda into aurora + GroupId: !GetAtt DBSecurityGroup.GroupId + IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupId: !Ref LambdaSecurityGroupId + BootstrapDatabaseLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + Path: / + Policies: + - PolicyName: secrets-manager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref AdminUserSecret + - !Ref MaintenanceUserSecret + - !Ref ReadwriteUserSecret + - !Ref ReadonlyUserSecret + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + BootstrapDatabaseLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/BootstrapDatabase.zip + Description: Database Init + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address + ADMIN_DATABASE_SECRET_ID: !Sub ${StackName}/AdminUserSecret + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${StackName}/MaintenanceUserSecret + READWRITE_DATABASE_SECRET_ID: !Sub ${StackName}/ReadwriteUserSecret + READONLY_DATABASE_SECRET_ID: !Sub ${StackName}/ReadonlyUserSecret + DATABASE_NAME: !Ref DatabaseName + FunctionName: !Sub ${StackName}-BootstrapDatabase + Handler: index.handle + MemorySize: 512 + Role: !GetAtt BootstrapDatabaseLambdaRole.Arn + Runtime: nodejs12.x + Timeout: 60 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + BootstrapDatabaseLambdaLambdaInvoker: + Type: Custom::BootstrapDatabaseLambdaInvoker + Properties: + ServiceToken: !GetAtt BootstrapDatabaseLambdaFunction.Arn + DependsOn: + - AdminUserSecretAttachment + - MaintenanceUserSecretAttachment + - ReadwriteUserSecretAttachment + - ReadonlyUserSecretAttachment + MigrateDatabaseLambdaRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Action: sts:AssumeRole + Principal: + Service: + - lambda.amazonaws.com + Path: / + Policies: + - PolicyName: secrets-manager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref MaintenanceUserSecret + - Effect: Allow + Action: + - s3:ListBucket + Resource: + - arn:aws:s3:::{{awsReleaseBucket}} + - Effect: Allow + Action: + - s3:GetObject* + Resource: + - arn:aws:s3:::{{awsReleaseBucket}}/* + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole + MigrateDatabaseLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/MigrateDatabase.zip + Description: Database Init + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + DATABASE_HOST: !GetAtt RDSCluster.Endpoint.Address + MAINTENANCE_DATABASE_SECRET_ID: !Sub ${StackName}/MaintenanceUserSecret + DATABASE_NAME: !Ref DatabaseName + MIGRATIONS_BUCKET: {{awsReleaseBucket}} + MIGRATIONS_LOCATION: migrations/{{version}} + FunctionName: !Sub ${StackName}-MigrateDatabase + Handler: index.handle + MemorySize: 512 + Role: !GetAtt MigrateDatabaseLambdaRole.Arn + Runtime: nodejs12.x + Timeout: 180 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + MigrateDatabaseLambdaLambdaInvoker: + Type: Custom::MigrateDatabaseLambdaInvoker + Properties: + ServiceToken: !GetAtt MigrateDatabaseLambdaFunction.Arn + DependsOn: BootstrapDatabaseLambdaLambdaInvoker +Outputs: + Identifier: + Value: !Ref RDSCluster diff --git a/packages/cloudformation/templates/givesource-cache.yml b/packages/cloudformation/templates/givesource-cache.yml new file mode 100644 index 00000000..1751b09c --- /dev/null +++ b/packages/cloudformation/templates/givesource-cache.yml @@ -0,0 +1,197 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: AWS Custom resources for Givesource(R) +Parameters: + + StackName: + Type: String + + LambdaRoleArn: + Type: String + + LambdaSecurityGroupId: + Type: String + + DefaultLambdaFunctionTimeout: + Type: Number + + CacheS3: + Type: String + +Resources: + + # Social Sharing Cache Resources + + PutSocialSharingLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/PutSocialSharing.zip + Description: "Put social sharing html file into s3" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET_NAME: !Ref CacheS3 + FunctionName: !Sub |- + ${StackName}-PutSocialSharing + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + PutNonprofitSocialSharingLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/PutNonprofitSocialSharing.zip + Description: "Put nonprofit social sharing html file into s3" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET_NAME: !Ref CacheS3 + FunctionName: !Sub |- + ${StackName}-PutNonprofitSocialSharing + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + WarmSocialSharingLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/WarmSocialSharing.zip + Description: "Warm social sharing and get initial html s3" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET_NAME: !Ref CacheS3 + FunctionName: !Sub |- + ${StackName}-WarmSocialSharing + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: 900 # In case there are a lot of Nonprofits to warm + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + WarmGivesourceSocialSharingLambdaLambdaInvoker: + Type: Custom::WarmSocialSharingLambdaInvoker + Properties: + ServiceToken: !GetAtt WarmSocialSharingLambdaFunction.Arn + DependsOn: + - PutSocialSharingLambdaFunction + - PutNonprofitSocialSharingLambdaFunction + + # SEO Cache Lambda Functions + + PutSEOLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/PutSEO.zip + Description: "Put seo file into s3" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET_NAME: !Ref CacheS3 + FunctionName: !Sub |- + ${StackName}-PutSEO + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + PutNonprofitSEOLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/PutNonprofitSEO.zip + Description: "Put nonprofit seo file into s3" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET_NAME: !Ref CacheS3 + FunctionName: !Sub |- + ${StackName}-PutNonprofitSEO + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: 300 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + WarmSEOLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/WarmSEO.zip + Description: "Warm social sharing and get initial html s3" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + AWS_S3_BUCKET_NAME: !Ref CacheS3 + FunctionName: !Sub |- + ${StackName}-WarmSEO + Handler: "index.handle" + MemorySize: 256 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: 900 # In case there are a lot of Nonprofits to warm + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet + + WarmSEOLambdaLambdaInvoker: + Type: Custom::WarmSEOLambdaInvoker + Properties: + ServiceToken: !GetAtt WarmSEOLambdaFunction.Arn + DependsOn: + - PutSEOLambdaFunction + - PutNonprofitSEOLambdaFunction diff --git a/packages/cloudformation/templates/givesource-custom.yml b/packages/cloudformation/templates/givesource-custom.yml index 1e36a55a..2ea4c0ff 100644 --- a/packages/cloudformation/templates/givesource-custom.yml +++ b/packages/cloudformation/templates/givesource-custom.yml @@ -6,12 +6,27 @@ Parameters: StackName: Type: String + ApiDistributionId: + Type: String + + ApiDistributionUrl: + Type: String + RestApi: Type: String LambdaRoleArn: Type: String + SecureLambdaRole: + Type: String + + SecureSettingsLambdaFunctionRole: + Type: String + + LambdaSecurityGroupId: + Type: String + DefaultLambdaFunctionTimeout: Type: Number @@ -42,9 +57,18 @@ Parameters: UploadsS3: Type: String + ReportsS3: + Type: String + UploadsCloudFrontUrl: Type: String + GivesourceCache: + Type: String + + CachingCloudFrontUrl: + Type: String + Resources: # Api Gateway Lambda Resources @@ -65,9 +89,16 @@ Resources: FunctionName: !Sub |- ${StackName}-AuthorizeUsers Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DependsOn: CognitoUserPool AuthorizeUsersLambdaInvokePermission: @@ -83,6 +114,28 @@ Resources: - AuthorizeUsersLambdaFunction - AuthorizeUsers + # Create Lambda Invalidation Function + + ApiDistributionInvalidationLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Sub |- + {{awsLambdaReleaseBucketPrefix}}-${AWS::Region} + S3Key: fn/{{version}}/ApiDistributionInvalidation.zip + Description: "Invalidate cloudfront cache for API Distribution for certain path(s)" + Environment: + Variables: + AWS_STACK_NAME: !Ref StackName + DISTRIBUTION_ID: !Ref ApiDistributionId + FunctionName: !Sub |- + ${StackName}-ApiDistributionInvalidation + Handler: "index.handle" + MemorySize: 128 + Role: !Ref LambdaRoleArn + Runtime: "nodejs12.x" + Timeout: !Ref DefaultLambdaFunctionTimeout + ApiGatewayFlushCacheLambdaFunction: Type: AWS::Lambda::Function Properties: @@ -98,6 +151,7 @@ Resources: FunctionName: !Sub |- ${StackName}-ApiGatewayFlushCache Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -150,9 +204,16 @@ Resources: FunctionName: !Sub |- ${StackName}-CognitoCreateUserPool Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DependsOn: CognitoCustomMessageFunction CognitoCreateUserPoolClientFunction: @@ -169,9 +230,16 @@ Resources: FunctionName: !Sub |- ${StackName}-CognitoCreateUserPoolClient Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCreateUserFunction: Type: AWS::Lambda::Function @@ -187,9 +255,16 @@ Resources: FunctionName: !Sub |- ${StackName}-CognitoCreateUser Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCreateUserGroupFunction: Type: AWS::Lambda::Function @@ -205,9 +280,16 @@ Resources: FunctionName: !Sub |- ${StackName}-CognitoCreateUserGroup Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCustomMessageFunction: Type: AWS::Lambda::Function @@ -226,9 +308,16 @@ Resources: FunctionName: !Sub |- ${StackName}-CognitoCustomMessage Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet CognitoCustomMessageLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -321,6 +410,7 @@ Resources: FunctionName: !Sub |- ${StackName}-GenerateCustomFrontendCss Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -342,6 +432,7 @@ Resources: FunctionName: !Sub |- ${StackName}-GenerateDynamicContent Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -448,7 +539,7 @@ Resources: FunctionName: !Sub |- ${StackName}-CreateLambdaEdgeFunction Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !GetAtt CreateLambdaEdgeFunctionRole.Arn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -468,7 +559,7 @@ Resources: FunctionName: !Sub |- ${StackName}-AssociateLambdaEdgeFunctions Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !GetAtt CreateLambdaEdgeFunctionRole.Arn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -490,6 +581,7 @@ Resources: FunctionName: !Sub |- ${StackName}-CreateParameter Handler: "index.handle" + MemorySize: 128 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -507,13 +599,20 @@ Resources: Environment: Variables: AWS_STACK_NAME: !Ref StackName - AWS_S3_BUCKET_NAME: !Ref UploadsS3 + AWS_S3_BUCKET_NAME: !Ref ReportsS3 FunctionName: !Sub |- ${StackName}-GenerateReport Handler: "index.handle" + MemorySize: 2048 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" - Timeout: !Ref DefaultLambdaFunctionTimeout + Timeout: 900 + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteReportsLambdaFunction: Type: AWS::Lambda::Function @@ -530,10 +629,16 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteReports Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet DeleteReportsLambdaInvokePermission: Type: AWS::Lambda::Permission @@ -562,9 +667,16 @@ Resources: FunctionName: !Sub |- ${StackName}-SaveSettings Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet # Secure Settings KMS Resources @@ -595,6 +707,34 @@ Resources: TargetKeyId: !Ref SecureSettingsKey DependsOn: SecureSettingsKey + SecureSettingsEncryptPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: secure_settings_encrypt + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: kms:Encrypt + Resource: + - !GetAtt SecureSettingsKey.Arn + Roles: + - !Ref SecureSettingsLambdaFunctionRole + + SecureSettingsDecryptPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: secure_settings_decrypt + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: kms:Decrypt + Resource: + - !GetAtt SecureSettingsKey.Arn + Roles: + - !Ref SecureLambdaRole + # S3 Lambda Resources S3PutObjectFunction: @@ -611,6 +751,7 @@ Resources: FunctionName: !Sub |- ${StackName}-S3PutObject Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -629,6 +770,7 @@ Resources: FunctionName: !Sub |- ${StackName}-S3SyncObjects Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -653,7 +795,7 @@ Resources: key: 'Content-Security-Policy', value: "default-src 'none'; " + "base-uri 'none'; " + - "connect-src 'self' https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com https://${UploadsS3}.s3.${AWS::Region}.amazonaws.com https://${UploadsS3}.s3.amazonaws.com https://cognito-idp.${AWS::Region}.amazonaws.com https://api.paymentspring.com https://vimeo.com; " + + "connect-src 'self' ${ApiDistributionUrl} https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com https://${UploadsS3}.s3.${AWS::Region}.amazonaws.com https://${UploadsS3}.s3.amazonaws.com https://cognito-idp.${AWS::Region}.amazonaws.com https://api.paymentspring.com https://vimeo.com; " + "font-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://fonts.gstatic.com https://use.fontawesome.com; " + "form-action 'self'; " + "frame-ancestors 'self'; " + @@ -693,7 +835,7 @@ Resources: key: 'Content-Security-Policy', value: "default-src 'none'; " + "base-uri 'none'; " + - "connect-src 'self' https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com https://cognito-idp.${AWS::Region}.amazonaws.com https://api.paymentspring.com; " + + "connect-src 'self' ${ApiDistributionUrl} https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com https://cognito-idp.${AWS::Region}.amazonaws.com https://api.paymentspring.com; " + "font-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://fonts.gstatic.com https://use.fontawesome.com; " + "form-action 'self'; " + "frame-ancestors 'self'; " + @@ -783,7 +925,8 @@ Resources: Value: !Sub |- { "AWS_STACK_REGION": "${AWS::Region}", - "AWS_STACK_NAME": "${StackName}" + "AWS_STACK_NAME": "${StackName}", + "AWS_S3_BUCKET_NAME": "${GivesourceCache}" } DependsOn: - CreateParameterLambdaFunction @@ -858,7 +1001,7 @@ Resources: Key: "settings.json" Body: !Sub |- { - "API_URL": "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/" + "API_URL": "${ApiDistributionUrl}" } DependsOn: - S3PutObjectFunction @@ -888,7 +1031,7 @@ Resources: Key: "settings.json" Body: !Sub |- { - "API_URL": "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/" + "API_URL": "${ApiDistributionUrl}" } DependsOn: - S3PutObjectFunction @@ -924,7 +1067,7 @@ Resources: ServiceToken: !GetAtt SaveSettingsLambdaFunction.Arn Settings: !Sub |- { - "API_URL": "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/", + "API_URL": "${ApiDistributionUrl}", "ADMIN_URL": "${AdminPagesCloudFrontUrl}", "ADMIN_PAGES_CLOUD_FRONT_URL": "${AdminPagesCloudFrontUrl}", "ADMIN_PAGES_S3_BUCKET_NAME": "${AdminPagesS3}", @@ -933,6 +1076,9 @@ Resources: "PUBLIC_PAGES_S3_BUCKET_NAME": "${PublicPagesS3}", "UPLOADS_CLOUD_FRONT_URL": "${UploadsCloudFrontUrl}", "UPLOADS_S3_BUCKET_NAME": "${UploadsS3}", + "CACHE_CLOUD_FRONT_URL": "${CachingCloudFrontUrl}", + "CACHE_S3_BUCKET_NAME": "${GivesourceCache}", + "REPORTS_S3_BUCKET_NAME": "${ReportsS3}", "USER_POOL_CLIENT_ID": "${CognitoUserPoolClient.UserPoolClientId}", "USER_POOL_ID": "${CognitoUserPool.UserPoolId}" } @@ -957,9 +1103,16 @@ Resources: FunctionName: !Sub |- ${StackName}-GenerateDonationsReceipt Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet SendDonationNotificationEmailLambdaFunction: Type: AWS::Lambda::Function @@ -975,9 +1128,16 @@ Resources: FunctionName: !Sub |- ${StackName}-SendDonationNotificationEmail Handler: "index.handle" + MemorySize: 512 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet SendDonationsReceiptEmailLambdaFunction: Type: AWS::Lambda::Function @@ -993,9 +1153,16 @@ Resources: FunctionName: !Sub |- ${StackName}-SendDonationsReceiptEmail Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet SendContactMessageEmailLambdaFunction: Type: AWS::Lambda::Function @@ -1011,9 +1178,16 @@ Resources: FunctionName: !Sub |- ${StackName}-SendContactMessageEmail Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet SendRegistrationPendingEmailLambdaFunction: Type: AWS::Lambda::Function @@ -1029,9 +1203,16 @@ Resources: FunctionName: !Sub |- ${StackName}-SendRegistrationPendingEmail Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet # Metrics lambda functions @@ -1049,9 +1230,16 @@ Resources: FunctionName: !Sub |- ${StackName}-MetricAddAmount Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet MetricMaxAmountLambdaFunction: Type: AWS::Lambda::Function @@ -1067,9 +1255,16 @@ Resources: FunctionName: !Sub |- ${StackName}-MetricMaxAmount Handler: "index.handle" + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout + VpcConfig: + SecurityGroupIds: + - !Ref LambdaSecurityGroupId + SubnetIds: + - !ImportValue givsource-primary-private-subnet + - !ImportValue givesource-secondary-private-subnet Outputs: @@ -1092,4 +1287,4 @@ Outputs: Value: !Ref SecureSettingsKeyAlias SecureSettingsKeyArn: - Value: !GetAtt SecureSettingsKey.Arn \ No newline at end of file + Value: !GetAtt SecureSettingsKey.Arn diff --git a/packages/cloudformation/templates/givesource-dynamo.yml b/packages/cloudformation/templates/givesource-dynamo.yml deleted file mode 100644 index 317869f9..00000000 --- a/packages/cloudformation/templates/givesource-dynamo.yml +++ /dev/null @@ -1,2384 +0,0 @@ ---- -AWSTemplateFormatVersion: 2010-09-09 -Description: AWS DynamoDB resources for Givesource(R) -Parameters: - StackName: - Type: String - - DefaultMinCapacity: - Type: Number - Default: 1 - - DefaultMaxReadCapacity: - Type: Number - Default: 50 - - DefaultMaxWriteCapacity: - Type: Number - Default: 10 - - DefaultTargetValue: - Type: Number - Default: 70 - - DefaultScaleInCooldown: - Type: Number - Default: 2700 - - ModerateTrafficMinCapacity: - Type: Number - Default: 1 - - ModerateTrafficMaxReadCapacity: - Type: Number - Default: 500 - - ModerateTrafficMaxWriteCapacity: - Type: Number - Default: 25 - - ModerateTrafficTargetValue: - Type: Number - Default: 60 - - HighTrafficMinCapacity: - Type: Number - Default: 1 - - HighTrafficMaxReadCapacity: - Type: Number - Default: 5000 - - HighTrafficMaxWriteCapacity: - Type: Number - Default: 50 - - HighTrafficTargetValue: - Type: Number - Default: 50 - -Metadata: - AWS::CloudFormation::Interface: - ParameterGroups: - - Label: - default: Stack Settings - Parameters: - - StackName - - - Label: - default: Default Auto-Scaling Settings - Parameters: - - DefaultMinCapacity - - DefaultMaxReadCapacity - - DefaultMaxWriteCapacity - - DefaultTargetValue - - DefaultScaleInCooldown - - - Label: - default: Moderate Traffic Auto-Scaling Settings - Parameters: - - ModerateTrafficMinCapacity - - ModerateTrafficMaxReadCapacity - - ModerateTrafficMaxWriteCapacity - - ModerateTrafficTargetValue - - - Label: - default: High Traffic Auto-Scaling Settings - Parameters: - - HighTrafficMinCapacity - - HighTrafficMaxReadCapacity - - HighTrafficMaxWriteCapacity - - HighTrafficTargetValue - -Resources: - ContentsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Contents - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: key - AttributeType: S - - AttributeName: parentUuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: keyIndex - KeySchema: - - AttributeName: key - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: parentUuidIndex - KeySchema: - - AttributeName: parentUuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - ContentsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ContentsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ContentsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${ContentsTable} - ScalingTargetId: !Ref ContentsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ContentsTableKeyReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ContentsTable}/index/keyIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ContentsTableKeyReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${ContentsTable}/index/keyIndex - ScalingTargetId: !Ref ContentsTableKeyReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ContentsTableParentUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ContentsTable}/index/parentUuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ContentsTableParentUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${ContentsTable}/index/parentUuidIndex - ScalingTargetId: !Ref ContentsTableParentUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ContentsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ContentsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ContentsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${ContentsTable} - ScalingTargetId: !Ref ContentsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ContentsTableKeyWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ContentsTable}/index/keyIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ContentsTableKeyWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${ContentsTable}/index/keyIndex - ScalingTargetId: !Ref ContentsTableKeyWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ContentsTableParentUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ContentsTable}/index/parentUuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ContentsTableParentUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${ContentsTable}/index/parentUuidIndex - ScalingTargetId: !Ref ContentsTableParentUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Donations - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: nonprofitUuid - AttributeType: S - - AttributeName: createdOn - AttributeType: N - - AttributeName: isDeleted - AttributeType: N - - AttributeName: subtotal - AttributeType: N - - AttributeName: donorUuid - AttributeType: S - - AttributeName: paymentTransactionIsTestMode - AttributeType: N - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: isDeletedCreatedOnIndex - KeySchema: - - AttributeName: isDeleted - KeyType: HASH - - AttributeName: createdOn - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: nonprofitUuidCreatedOnIndex - KeySchema: - - AttributeName: nonprofitUuid - KeyType: HASH - - AttributeName: createdOn - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: nonprofitUuidSubtotalIndex - KeySchema: - - AttributeName: nonprofitUuid - KeyType: HASH - - AttributeName: subtotal - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: paymentTransactionIsTestModeCreatedOnIndex - KeySchema: - - AttributeName: paymentTransactionIsTestMode - KeyType: HASH - - AttributeName: createdOn - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: donorUuidCreatedOnIndex - KeySchema: - - AttributeName: donorUuid - KeyType: HASH - - AttributeName: createdOn - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: ContentsTable - - DonationsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonationsTable} - ScalingTargetId: !Ref DonationsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableDonorUuidCreatedOnIndexReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/donorUuidCreatedOnIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableDonorUuidCreatedOnIndexReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonationsTable}/index/donorUuidCreatedOnIndex - ScalingTargetId: !Ref DonationsTableDonorUuidCreatedOnIndexReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableIsDeletedCreatedOnReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/isDeletedCreatedOnIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableIsDeletedCreatedOnReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonationsTable}/index/isDeletedCreatedOnIndex - ScalingTargetId: !Ref DonationsTableIsDeletedCreatedOnReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableNonprofitUuidCreatedOnReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/nonprofitUuidCreatedOnIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableNonprofitUuidCreatedOnReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonationsTable}/index/nonprofitUuidCreatedOnIndex - ScalingTargetId: !Ref DonationsTableNonprofitUuidCreatedOnReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableNonprofitUuidSubtotalReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/nonprofitUuidSubtotalIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableNonprofitUuidSubtotalReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonationsTable}/index/nonprofitUuidSubtotalIndex - ScalingTargetId: !Ref DonationsTableNonprofitUuidSubtotalReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTablePaymentTransactionIsTestModeCreatedOnReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/paymentTransactionIsTestModeCreatedOnIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTablePaymentTransactionIsTestModeCreatedOnReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonationsTable}/index/paymentTransactionIsTestModeCreatedOnIndex - ScalingTargetId: !Ref DonationsTablePaymentTransactionIsTestModeCreatedOnReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonationsTable} - ScalingTargetId: !Ref DonationsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableDonorUuidCreatedOnWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/donorUuidCreatedOnIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableDonorUuidCreatedOnWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonationsTable}/index/donorUuidCreatedOnIndex - ScalingTargetId: !Ref DonationsTableDonorUuidCreatedOnWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableIsDeletedCreatedOnWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/isDeletedCreatedOnIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableIsDeletedCreatedOnWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonationsTable}/index/isDeletedCreatedOnIndex - ScalingTargetId: !Ref DonationsTableIsDeletedCreatedOnWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableNonprofitUuidCreatedOnWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/nonprofitUuidCreatedOnIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableNonprofitUuidCreatedOnWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonationsTable}/index/nonprofitUuidCreatedOnIndex - ScalingTargetId: !Ref DonationsTableNonprofitUuidCreatedOnWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTableNonprofitUuidSubtotalWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/nonprofitUuidSubtotalIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTableNonprofitUuidSubtotalWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonationsTable}/index/nonprofitUuidSubtotalIndex - ScalingTargetId: !Ref DonationsTableNonprofitUuidSubtotalWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonationsTablePaymentTransactionIsTestModeCreatedOnWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonationsTable}/index/paymentTransactionIsTestModeCreatedOnIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonationsTablePaymentTransactionIsTestModeCreatedOnWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonationsTable}/index/paymentTransactionIsTestModeCreatedOnIndex - ScalingTargetId: !Ref DonationsTablePaymentTransactionIsTestModeCreatedOnWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonorsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Donors - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: email - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: emailIndex - KeySchema: - - AttributeName: email - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: DonationsTable - - DonorsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonorsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonorsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonorsTable} - ScalingTargetId: !Ref DonorsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonorsTableEmailReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonorsTable}/index/emailIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonorsTableEmailReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${DonorsTable}/index/emailIndex - ScalingTargetId: !Ref DonorsTableEmailReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonorsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonorsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonorsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonorsTable} - ScalingTargetId: !Ref DonorsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - DonorsTableEmailWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${DonorsTable}/index/emailIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - DonorsTableEmailWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${DonorsTable}/index/emailIndex - ScalingTargetId: !Ref DonorsTableEmailWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - FilesTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Files - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: DonorsTable - - FilesTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${FilesTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - FilesTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${FilesTable} - ScalingTargetId: !Ref FilesTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - FilesTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${FilesTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - FilesTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${FilesTable} - ScalingTargetId: !Ref FilesTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MessagesTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Messages - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: FilesTable - - MessagesTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MessagesTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MessagesTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${MessagesTable} - ScalingTargetId: !Ref MessagesTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MessagesTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MessagesTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MessagesTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${MessagesTable} - ScalingTargetId: !Ref MessagesTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MetricsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Metrics - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: createdOn - AttributeType: N - - AttributeName: key - AttributeType: S - KeySchema: - - AttributeName: key - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: uuidIndex - KeySchema: - - AttributeName: uuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: createdOnIndex - KeySchema: - - AttributeName: createdOn - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: MessagesTable - - MetricsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MetricsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MetricsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${MetricsTable} - ScalingTargetId: !Ref MetricsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MetricsTableCreatedOnReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MetricsTable}/index/createdOnIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MetricsTableCreatedOnReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${MetricsTable}/index/createdOnIndex - ScalingTargetId: !Ref MetricsTableCreatedOnReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MetricsTableUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MetricsTable}/index/uuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MetricsTableUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${MetricsTable}/index/uuidIndex - ScalingTargetId: !Ref MetricsTableUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MetricsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MetricsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MetricsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${MetricsTable} - ScalingTargetId: !Ref MetricsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MetricsTableCreatedOnWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MetricsTable}/index/createdOnIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MetricsTableCreatedOnWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${MetricsTable}/index/createdOnIndex - ScalingTargetId: !Ref MetricsTableCreatedOnWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - MetricsTableUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${MetricsTable}/index/uuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - MetricsTableUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${MetricsTable}/index/uuidIndex - ScalingTargetId: !Ref MetricsTableUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Nonprofits - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: createdOn - AttributeType: N - - AttributeName: status - AttributeType: S - - AttributeName: slug - AttributeType: S - - AttributeName: isDeleted - AttributeType: N - - AttributeName: donationsSubtotal - AttributeType: N - - AttributeName: legalNameSearch - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: isDeletedCreatedOnIndex - KeySchema: - - AttributeName: isDeleted - KeyType: HASH - - AttributeName: createdOn - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: isDeletedLegalNameIndex - KeySchema: - - AttributeName: isDeleted - KeyType: HASH - - AttributeName: legalNameSearch - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: statusLegalNameIndex - KeySchema: - - AttributeName: status - KeyType: HASH - - AttributeName: legalNameSearch - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: statusSubtotalIndex - KeySchema: - - AttributeName: status - KeyType: HASH - - AttributeName: donationsSubtotal - KeyType: RANGE - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: slugIndex - KeySchema: - - AttributeName: slug - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: MetricsTable - - NonprofitsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitsTable} - ScalingTargetId: !Ref NonprofitsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableIsDeletedCreatedOnReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/isDeletedCreatedOnIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableIsDeletedCreatedOnReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitsTable}/index/isDeletedCreatedOnIndex - ScalingTargetId: !Ref NonprofitsTableIsDeletedCreatedOnReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableIsDeletedLegalNameReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/isDeletedLegalNameIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableIsDeletedLegalNameReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitsTable}/index/isDeletedLegalNameIndex - ScalingTargetId: !Ref NonprofitsTableIsDeletedLegalNameReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableSlugReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/slugIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableSlugReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitsTable}/index/slugIndex - ScalingTargetId: !Ref NonprofitsTableSlugReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableStatusLegalNameReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/statusLegalNameIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableStatusLegalNameReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitsTable}/index/statusLegalNameIndex - ScalingTargetId: !Ref NonprofitsTableStatusLegalNameReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableStatusSubtotalReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/statusSubtotalIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableStatusSubtotalReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitsTable}/index/statusSubtotalIndex - ScalingTargetId: !Ref NonprofitsTableStatusSubtotalReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitsTable} - ScalingTargetId: !Ref NonprofitsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableIsDeletedCreatedOnWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/isDeletedCreatedOnIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableIsDeletedCreatedOnWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitsTable}/index/isDeletedCreatedOnIndex - ScalingTargetId: !Ref NonprofitsTableIsDeletedCreatedOnWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableIsDeletedLegalNameWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/isDeletedLegalNameIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableIsDeletedLegalNameWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitsTable}/index/isDeletedLegalNameIndex - ScalingTargetId: !Ref NonprofitsTableIsDeletedLegalNameWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableSlugWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/slugIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableSlugWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitsTable}/index/slugIndex - ScalingTargetId: !Ref NonprofitsTableSlugWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableStatusLegalNameWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/statusLegalNameIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableStatusLegalNameWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitsTable}/index/statusLegalNameIndex - ScalingTargetId: !Ref NonprofitsTableStatusLegalNameWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitsTableStatusSubtotalWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitsTable}/index/statusSubtotalIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitsTableStatusSubtotalWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitsTable}/index/statusSubtotalIndex - ScalingTargetId: !Ref NonprofitsTableStatusSubtotalWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitDonationTiersTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-NonprofitDonationTiers - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: nonprofitUuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: nonprofitUuidIndex - KeySchema: - - AttributeName: nonprofitUuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: NonprofitsTable - - NonprofitDonationTiersTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitDonationTiersTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitDonationTiersTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitDonationTiersTable} - ScalingTargetId: !Ref NonprofitDonationTiersTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitDonationTiersTableNonprofitUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitDonationTiersTable}/index/nonprofitUuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitDonationTiersTableNonprofitUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitDonationTiersTable}/index/nonprofitUuidIndex - ScalingTargetId: !Ref NonprofitDonationTiersTableNonprofitUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitDonationTiersTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitDonationTiersTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitDonationTiersTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitDonationTiersTable} - ScalingTargetId: !Ref NonprofitDonationTiersTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitDonationTiersTableNonprofitUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitDonationTiersTable}/index/nonprofitUuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitDonationTiersTableNonprofitUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitDonationTiersTable}/index/nonprofitUuidIndex - ScalingTargetId: !Ref NonprofitDonationTiersTableNonprofitUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitSlidesTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-NonprofitSlides - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: nonprofitUuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: nonprofitUuidIndex - KeySchema: - - AttributeName: nonprofitUuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: NonprofitDonationTiersTable - - NonprofitSlidesTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitSlidesTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitSlidesTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitSlidesTable} - ScalingTargetId: !Ref NonprofitSlidesTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitSlidesTableNonprofitUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitSlidesTable}/index/nonprofitUuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitSlidesTableNonprofitUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${NonprofitSlidesTable}/index/nonprofitUuidIndex - ScalingTargetId: !Ref NonprofitSlidesTableNonprofitUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitSlidesTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitSlidesTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitSlidesTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitSlidesTable} - ScalingTargetId: !Ref NonprofitSlidesTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - NonprofitSlidesTableNonprofitUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${NonprofitSlidesTable}/index/nonprofitUuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref HighTrafficMinCapacity - MaxCapacity: !Ref HighTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - NonprofitSlidesTableNonprofitUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${NonprofitSlidesTable}/index/nonprofitUuidIndex - ScalingTargetId: !Ref NonprofitSlidesTableNonprofitUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref HighTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - PaymentTransactionsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-PaymentTransactions - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: NonprofitSlidesTable - - PaymentTransactionsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${PaymentTransactionsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - PaymentTransactionsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${PaymentTransactionsTable} - ScalingTargetId: !Ref PaymentTransactionsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - PaymentTransactionsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${PaymentTransactionsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - PaymentTransactionsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${PaymentTransactionsTable} - ScalingTargetId: !Ref PaymentTransactionsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ReportsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Reports - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: PaymentTransactionsTable - - ReportsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ReportsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ReportsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${ReportsTable} - ScalingTargetId: !Ref ReportsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - ReportsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${ReportsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - ReportsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${ReportsTable} - ScalingTargetId: !Ref ReportsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SettingsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Settings - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: key - AttributeType: S - KeySchema: - - AttributeName: key - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: uuidIndex - KeySchema: - - AttributeName: uuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: ReportsTable - - SettingsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SettingsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SettingsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${SettingsTable} - ScalingTargetId: !Ref SettingsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SettingsTableUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SettingsTable}/index/uuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SettingsTableUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${SettingsTable}/index/uuidIndex - ScalingTargetId: !Ref SettingsTableUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SettingsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SettingsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SettingsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${SettingsTable} - ScalingTargetId: !Ref SettingsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SettingsTableUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SettingsTable}/index/uuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SettingsTableUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${SettingsTable}/index/uuidIndex - ScalingTargetId: !Ref SettingsTableUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorsTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Sponsors - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: sponsorTierUuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: sponsorTierUuidIndex - KeySchema: - - AttributeName: sponsorTierUuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: SettingsTable - - SponsorsTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorsTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorsTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${SponsorsTable} - ScalingTargetId: !Ref SponsorsTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorsTableSponsorTierUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorsTable}/index/sponsorTierUuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorsTableSponsorTierUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${SponsorsTable}/index/sponsorTierUuidIndex - ScalingTargetId: !Ref SponsorsTableSponsorTierUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorsTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorsTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorsTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${SponsorsTable} - ScalingTargetId: !Ref SponsorsTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorsTableSponsorTierUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorsTable}/index/sponsorTierUuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorsTableSponsorTierUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${SponsorsTable}/index/sponsorTierUuidIndex - ScalingTargetId: !Ref SponsorsTableSponsorTierUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorTiersTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-SponsorTiers - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: name - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: nameIndex - KeySchema: - - AttributeName: name - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: SponsorsTable - - SponsorTiersTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorTiersTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorTiersTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${SponsorTiersTable} - ScalingTargetId: !Ref SponsorTiersTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorTiersTableNameReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorTiersTable}/index/nameIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorTiersTableNameReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${SponsorTiersTable}/index/nameIndex - ScalingTargetId: !Ref SponsorTiersTableNameReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorTiersTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorTiersTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorTiersTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${SponsorTiersTable} - ScalingTargetId: !Ref SponsorTiersTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - SponsorTiersTableNameWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${SponsorTiersTable}/index/nameIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref DefaultMinCapacity - MaxCapacity: !Ref DefaultMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - SponsorTiersTableNameWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${SponsorTiersTable}/index/nameIndex - ScalingTargetId: !Ref SponsorTiersTableNameWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref DefaultTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - UsersTable: - Type: AWS::DynamoDB::Table - Properties: - TableName: !Sub |- - ${StackName}-Users - AttributeDefinitions: - - AttributeName: uuid - AttributeType: S - - AttributeName: email - AttributeType: S - - AttributeName: cognitoUuid - AttributeType: S - KeySchema: - - AttributeName: uuid - KeyType: HASH - PointInTimeRecoverySpecification: - PointInTimeRecoveryEnabled: true - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - GlobalSecondaryIndexes: - - IndexName: emailIndex - KeySchema: - - AttributeName: email - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - - IndexName: cognitoUuidIndex - KeySchema: - - AttributeName: cognitoUuid - KeyType: HASH - Projection: - ProjectionType: ALL - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - DependsOn: SponsorTiersTable - - UsersTableReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${UsersTable} - ScalableDimension: dynamodb:table:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - UsersTableReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${UsersTable} - ScalingTargetId: !Ref UsersTableReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - UsersTableCognitoUuidReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${UsersTable}/index/cognitoUuidIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - UsersTableCognitoUuidReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${UsersTable}/index/cognitoUuidIndex - ScalingTargetId: !Ref UsersTableCognitoUuidReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - UsersTableEmailReadScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${UsersTable}/index/emailIndex - ScalableDimension: dynamodb:index:ReadCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxReadCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - UsersTableEmailReadScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBReadCapacityUtilization:table/${UsersTable}/index/emailIndex - ScalingTargetId: !Ref UsersTableEmailReadScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBReadCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - UsersTableWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${UsersTable} - ScalableDimension: dynamodb:table:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - UsersTableWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${UsersTable} - ScalingTargetId: !Ref UsersTableWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - UsersTableCognitoUuidWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${UsersTable}/index/cognitoUuidIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - UsersTableCognitoUuidWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${UsersTable}/index/cognitoUuidIndex - ScalingTargetId: !Ref UsersTableCognitoUuidWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - - UsersTableEmailWriteScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - ServiceNamespace: dynamodb - ResourceId: !Sub table/${UsersTable}/index/emailIndex - ScalableDimension: dynamodb:index:WriteCapacityUnits - MinCapacity: !Ref ModerateTrafficMinCapacity - MaxCapacity: !Ref ModerateTrafficMaxWriteCapacity - RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable - - UsersTableEmailWriteScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: !Sub DynamoDBWriteCapacityUtilization:table/${UsersTable}/index/emailIndex - ScalingTargetId: !Ref UsersTableEmailWriteScalingTarget - PolicyType: TargetTrackingScaling - TargetTrackingScalingPolicyConfiguration: - PredefinedMetricSpecification: - PredefinedMetricType: DynamoDBWriteCapacityUtilization - TargetValue: !Ref ModerateTrafficTargetValue - DisableScaleIn: false - ScaleInCooldown: !Ref DefaultScaleInCooldown - -Outputs: - ContentsTable: - Value: !Ref ContentsTable - - DonationsTable: - Value: !Ref DonationsTable - - DonorsTable: - Value: !Ref DonorsTable - - FilesTable: - Value: !Ref FilesTable - - MessagesTable: - Value: !Ref MessagesTable - - MetricsTable: - Value: !Ref MetricsTable - - NonprofitsTable: - Value: !Ref NonprofitsTable - - NonprofitDonationTiersTable: - Value: !Ref NonprofitDonationTiersTable - - NonprofitSlidesTable: - Value: !Ref NonprofitSlidesTable - - PaymentTransactionsTable: - Value: !Ref PaymentTransactionsTable - - ReportsTable: - Value: !Ref ReportsTable - - SettingsTable: - Value: !Ref SettingsTable - - SponsorsTable: - Value: !Ref SponsorsTable - - SponsorTiersTable: - Value: !Ref SponsorTiersTable - - UsersTable: - Value: !Ref UsersTable \ No newline at end of file diff --git a/packages/cloudformation/templates/givesource-events.yml b/packages/cloudformation/templates/givesource-events.yml index e980fb6c..05ae4566 100644 --- a/packages/cloudformation/templates/givesource-events.yml +++ b/packages/cloudformation/templates/givesource-events.yml @@ -46,7 +46,7 @@ Resources: FunctionName: !Sub |- ${StackName}-DeleteReports Handler: "index.handle" - MemorySize: 128 + MemorySize: 256 Role: !Ref LambdaRoleArn Runtime: "nodejs12.x" Timeout: !Ref DefaultLambdaFunctionTimeout @@ -60,4 +60,4 @@ Resources: SourceArn: !GetAtt HourlyScheduledEventRule.Arn DependsOn: - DeleteReportsLambdaFunction - - HourlyScheduledEventRule \ No newline at end of file + - HourlyScheduledEventRule diff --git a/packages/cloudformation/templates/givesource-monitoring.yml b/packages/cloudformation/templates/givesource-monitoring.yml index b3fb2ed6..69374466 100644 --- a/packages/cloudformation/templates/givesource-monitoring.yml +++ b/packages/cloudformation/templates/givesource-monitoring.yml @@ -34,64 +34,8 @@ Parameters: Type: CommaDelimitedList Default: "" - ContentsTable: - Description: The name of the contents table - Type: String - - DonationsTable: - Description: The name of the donations table - Type: String - - DonorsTable: - Description: The name of the donors table - Type: String - - FilesTable: - Description: The name of the files table - Type: String - - MessagesTable: - Description: The name of the messages table - Type: String - - MetricsTable: - Description: The name of the metrics table - Type: String - - NonprofitsTable: - Description: The name of the noprofits table - Type: String - - NonprofitDonationTiersTable: - Description: The name of the nonprofit donations tiers table - Type: String - - NonprofitSlidesTable: - Description: The name of the nonprofit slides table - Type: String - - PaymentTransactionsTable: - Description: The name of the payment transactions table - Type: String - - ReportsTable: - Description: The name of the reports table - Type: String - - SettingsTable: - Description: The name of the settings table - Type: String - - SponsorsTable: - Description: The name of the sponsors table - Type: String - - SponsorTiersTable: - Description: The name of the sponsor tiers table - Type: String - - UsersTable: - Description: The name of the users table + DatabaseIdentifier: + Description: The identifier of the rds database Type: String Conditions: @@ -370,669 +314,144 @@ Resources: EvaluationPeriods: 1 TreatMissingData: notBreaching - ContentsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${ContentsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref ContentsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - ContentsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${ContentsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref ContentsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - DonationsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${DonationsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref DonationsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - DonationsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${DonationsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref DonationsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - DonorsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${DonorsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref DonorsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - DonorsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${DonorsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref DonorsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - FilesTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${FilesTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref FilesTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - FilesTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${FilesTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref FilesTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - MessagesTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${MessagesTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref MessagesTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - MessagesTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${MessagesTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref MessagesTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - MetricsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${MetricsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref MetricsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - MetricsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${MetricsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref MetricsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - NonprofitsTableReadThrottleAlarm: + rdsCpuUtilizationAlarm: Type: AWS::CloudWatch::Alarm Properties: ActionsEnabled: true - AlarmDescription: !Sub ${NonprofitsTable} ReadThrottleEvents + AlarmDescription: !Sub ${StackName} RDS CPUUtilization Alarm AlarmActions: - !Ref AlertSns OKActions: - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents + Namespace: AWS/RDS + MetricName: CPUUtilization Dimensions: - - Name: TableName - Value: !Ref NonprofitsTable + - Name: DBClusterIdentifier + Value: !Ref DatabaseIdentifier Statistic: Sum - Period: 60 + Period: 300 ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 + Threshold: 90 + EvaluationPeriods: 1 TreatMissingData: notBreaching - NonprofitsTableWriteThrottleAlarm: + rdsCpuUtilizationAlarm: Type: AWS::CloudWatch::Alarm Properties: ActionsEnabled: true - AlarmDescription: !Sub ${NonprofitsTable} WriteThrottleEvents + AlarmDescription: !Sub ${StackName} RDS CPUUtilization Alarm AlarmActions: - !Ref AlertSns OKActions: - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents + Namespace: AWS/RDS + MetricName: CPUUtilization Dimensions: - - Name: TableName - Value: !Ref NonprofitsTable + - Name: DBClusterIdentifier + Value: !Ref DatabaseIdentifier Statistic: Sum Period: 60 ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching + Threshold: 90 + EvaluationPeriods: 1 + TreatMissingData: breaching - NonprofitDonationTiersTableReadThrottleAlarm: + rdsFreeLocalStorageAlarm: Type: AWS::CloudWatch::Alarm Properties: ActionsEnabled: true - AlarmDescription: !Sub ${NonprofitDonationTiersTable} ReadThrottleEvents + AlarmDescription: !Sub ${StackName} RDS FreeLocalStorage Alarm AlarmActions: - !Ref AlertSns OKActions: - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents + Namespace: AWS/RDS + MetricName: FreeLocalStorage Dimensions: - - Name: TableName - Value: !Ref NonprofitDonationTiersTable + - Name: DBClusterIdentifier + Value: !Ref DatabaseIdentifier Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching + Period: 300 + ComparisonOperator: LessThanThreshold + # < 10GB + Threshold: 10737418240 + EvaluationPeriods: 1 + TreatMissingData: breaching - NonprofitDonationTiersTableWriteThrottleAlarm: + rdsFreeableMemoryAlarm: Type: AWS::CloudWatch::Alarm Properties: ActionsEnabled: true - AlarmDescription: !Sub ${NonprofitDonationTiersTable} WriteThrottleEvents + AlarmDescription: !Sub ${StackName} RDS FreeableMemory Alarm AlarmActions: - !Ref AlertSns OKActions: - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents + Namespace: AWS/RDS + MetricName: FreeableMemory Dimensions: - - Name: TableName - Value: !Ref NonprofitDonationTiersTable + - Name: DBClusterIdentifier + Value: !Ref DatabaseIdentifier Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching + Period: 300 + ComparisonOperator: LessThanThreshold + # < 512MB + Threshold: 536870912 + EvaluationPeriods: 1 + TreatMissingData: breaching - NonprofitSlidesTableReadThrottleAlarm: + processDonationsLambdaSlowAlarm: Type: AWS::CloudWatch::Alarm Properties: ActionsEnabled: true - AlarmDescription: !Sub ${NonprofitSlidesTable} ReadThrottleEvents + AlarmDescription: !Sub ${StackName} processDonations Lambda Slow Alarm AlarmActions: - !Ref AlertSns OKActions: - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents + Namespace: AWS/Lambda + MetricName: Duration Dimensions: - - Name: TableName - Value: !Ref NonprofitSlidesTable - Statistic: Sum + - Name: FunctionName + Value: !Sub ${StackName}-ProcessDonations + Statistic: Maximum Period: 60 ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 + Threshold: 27000 + EvaluationPeriods: 1 TreatMissingData: notBreaching - NonprofitSlidesTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm + DbSlowQueryMetricFilter: + Type: AWS::Logs::MetricFilter Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${NonprofitSlidesTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref NonprofitSlidesTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - PaymentTransactionsTableReadThrottleAlarm: + LogGroupName: !Sub /aws/rds/cluster/${DatabaseIdentifier}/slowquery + FilterPattern: '' + MetricTransformations: + - MetricNamespace: !Ref StackName + MetricName: SlowQueryLogs + MetricValue: 1 + DefaultValue: 0 + + DbSlowQueryAlarm: Type: AWS::CloudWatch::Alarm Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${PaymentTransactionsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref PaymentTransactionsTable + AlarmName: !Sub "${StackName}-DbSlowQuery" + AlarmDescription: Alarms when query takes >10s on the database + #AlarmActions: + # - !Ref AlertSns + #OKActions: + # - !Ref AlertSns + MetricName: SlowQueryLogs + Namespace: !Ref StackName + ComparisonOperator: GreaterThanOrEqualToThreshold + EvaluationPeriods: 1 + Period: 300 Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 + Threshold: 1 TreatMissingData: notBreaching - PaymentTransactionsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${PaymentTransactionsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref PaymentTransactionsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - ReportsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${ReportsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref ReportsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - ReportsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${ReportsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref ReportsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - SettingsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${SettingsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref SettingsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - SettingsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${SettingsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref SettingsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - SponsorsTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${SponsorsTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref SponsorsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - SponsorsTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${SponsorsTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref SponsorsTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - SponsorTiersTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${SponsorTiersTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref SponsorTiersTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - SponsorTiersTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${SponsorTiersTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref SponsorTiersTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - UsersTableReadThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${UsersTable} ReadThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: ReadThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref UsersTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - UsersTableWriteThrottleAlarm: - Type: AWS::CloudWatch::Alarm - Properties: - ActionsEnabled: true - AlarmDescription: !Sub ${UsersTable} WriteThrottleEvents - AlarmActions: - - !Ref AlertSns - OKActions: - - !Ref AlertSns - Namespace: AWS/DynamoDB - MetricName: WriteThrottleEvents - Dimensions: - - Name: TableName - Value: !Ref UsersTable - Statistic: Sum - Period: 60 - ComparisonOperator: GreaterThanThreshold - Threshold: 0 - EvaluationPeriods: 10 - DatapointsToAlarm: 3 - TreatMissingData: notBreaching - - - Dashboard: - Type: AWS::CloudWatch::Dashboard + Dashboard: + Type: AWS::CloudWatch::Dashboard Properties: DashboardName: !Ref StackName DashboardBody: !Sub @@ -1342,6 +761,11 @@ Resources: "AWS/Lambda", "Errors", "FunctionName", + "${StackName}-AdminPostDonationsReceipt", + {"label": "AdminPostDonationsReceipt"} + ], + [ + "...", "${StackName}-AdminRegisterNonprofit", {"label": "AdminRegisterNonprofit"} ], @@ -1360,6 +784,11 @@ Resources: "${StackName}-AuthorizeUsers", {"label": "AuthorizeUsers"} ], + [ + "...", + "${StackName}-BootstrapDatabase", + {"label": "BootstrapDatabase"} + ], [ "...", "${StackName}-CognitoCreateUser", @@ -1405,6 +834,16 @@ Resources: "${StackName}-DeleteContents", {"label": "DeleteContents"} ], + [ + "...", + "${StackName}-DeleteDonation", + {"label": "DeleteDonation"} + ], + [ + "...", + "${StackName}-DeleteDonor", + {"label": "DeleteDonor"} + ], [ "...", "${StackName}-DeleteFile", @@ -1415,6 +854,31 @@ Resources: "${StackName}-DeleteFiles", {"label": "DeleteFiles"} ], + [ + "...", + "${StackName}-DeleteMessage", + {"label": "DeleteMessage"} + ], + [ + "...", + "${StackName}-DeleteMetrics", + {"label": "DeleteMetrics"} + ], + [ + "...", + "${StackName}-DeleteNonprofit", + {"label": "DeleteNonprofit"} + ], + [ + "...", + "${StackName}-DeleteNonprofitDonation", + {"label": "DeleteNonprofitDonation"} + ], + [ + "...", + "${StackName}-DeleteNonprofitDonationTiers", + {"label": "DeleteNonprofitDonationTiers"} + ], [ "...", "${StackName}-DeleteNonprofitSlide", @@ -1425,21 +889,51 @@ Resources: "${StackName}-DeleteNonprofitUser", {"label": "DeleteNonprofitUser"} ], + [ + "...", + "${StackName}-DeletePaymentTransaction", + {"label": "DeletePaymentTransaction"} + ], [ "...", "${StackName}-DeleteReports", {"label": "DeleteReports"} ], + [ + "...", + "${StackName}-DeleteSetting", + {"label": "DeleteSetting"} + ], [ "...", "${StackName}-DeleteSettings", {"label": "DeleteSettings"} ], + [ + "...", + "${StackName}-DeleteSponsor", + {"label": "DeleteSponsor"} + ], + [ + "...", + "${StackName}-DeleteSponsorTier", + {"label": "DeleteSponsorTier"} + ], + [ + "...", + "${StackName}-DeleteSponsors", + {"label": "DeleteSponsors"} + ], [ "...", "${StackName}-DeleteUser", {"label": "DeleteUser"} ], + [ + "...", + "${StackName}-DownloadFile", + {"label": "DownloadFile"} + ], [ "...", "${StackName}-GenerateCustomFrontendCss", @@ -1455,6 +949,11 @@ Resources: "${StackName}-GenerateDynamicContent", {"label": "GenerateDynamicContent"} ], + [ + "...", + "${StackName}-GeneratePublicPagesHtml", + {"label": "GeneratePublicPagesHtml"} + ], [ "...", "${StackName}-GenerateReport", @@ -1465,11 +964,31 @@ Resources: "${StackName}-GetContents", {"label": "GetContents"} ], + [ + "...", + "${StackName}-GetDonation", + {"label": "GetDonation"} + ], [ "...", "${StackName}-GetDonations", {"label": "GetDonations"} ], + [ + "...", + "${StackName}-GetDonationsReceipt", + {"label": "GetDonationsReceipt"} + ], + [ + "...", + "${StackName}-GetDonor", + {"label": "GetDonor"} + ], + [ + "...", + "${StackName}-GetDonors", + {"label": "GetDonors"} + ], [ "...", "${StackName}-GetEmail", @@ -1485,6 +1004,16 @@ Resources: "${StackName}-GetFiles", {"label": "GetFiles"} ], + [ + "...", + "${StackName}-GetMessage", + {"label": "GetMessage"} + ], + [ + "...", + "${StackName}-GetMessages", + {"label": "GetMessages"} + ], [ "...", "${StackName}-GetMetrics", @@ -1495,11 +1024,21 @@ Resources: "${StackName}-GetNonprofit", {"label": "GetNonprofit"} ], + [ + "...", + "${StackName}-GetNonprofitDonation", + {"label": "GetNonprofitDonation"} + ], [ "...", "${StackName}-GetNonprofitDonations", {"label": "GetNonprofitDonations"} ], + [ + "...", + "${StackName}-GetNonprofitDonationTier", + {"label": "GetNonprofitDonationTier"} + ], [ "...", "${StackName}-GetNonprofitDonationTiers", @@ -1510,6 +1049,11 @@ Resources: "${StackName}-GetNonprofitPage", {"label": "GetNonprofitPage"} ], + [ + "...", + "${StackName}-GetNonprofitReport", + {"label": "GetNonprofitReport"} + ], [ "...", "${StackName}-GetNonprofits", @@ -1530,6 +1074,16 @@ Resources: "${StackName}-GetNonprofitUsers", {"label": "GetNonprofitUsers"} ], + [ + "...", + "${StackName}-GetPaymentTransaction", + {"label": "GetPaymentTransaction"} + ], + [ + "...", + "${StackName}-GetPaymentTransactions", + {"label": "GetPaymentTransactions"} + ], [ "...", "${StackName}-GetReport", @@ -1595,16 +1149,46 @@ Resources: "${StackName}-MetricMaxAmount", {"label": "MetricMaxAmount"} ], + [ + "...", + "${StackName}-MigrateDatabase", + {"label": "MigrateDatabase"} + ], + [ + "...", + "${StackName}-PatchContent", + {"label": "PatchContent"} + ], [ "...", "${StackName}-PatchContents", {"label": "PatchContents"} ], + [ + "...", + "${StackName}-PatchDonation", + {"label": "PatchDonation"} + ], + [ + "...", + "${StackName}-PatchMessage", + {"label": "PatchMessage"} + ], + [ + "...", + "${StackName}-PatchMetrics", + {"label": "PatchMetrics"} + ], [ "...", "${StackName}-PatchNonprofit", {"label": "PatchNonprofit"} ], + [ + "...", + "${StackName}-PatchNonprofitDonation", + {"label": "PatchNonprofitDonation"} + ], [ "...", "${StackName}-PatchNonprofitDonationTiers", @@ -1625,6 +1209,11 @@ Resources: "${StackName}-PatchNonprofitStatus", {"label": "PatchNonprofitStatus"} ], + [ + "...", + "${StackName}-PatchPaymentTransaction", + {"label": "PatchPaymentTransaction"} + ], [ "...", "${StackName}-PatchSecureSetting", @@ -1662,14 +1251,29 @@ Resources: ], [ "...", - "${StackName}-PatchUser", - {"label": "PatchUser"} + "${StackName}-PatchSponsorTiers", + {"label": "PatchSponsorTiers"} + ], + [ + "...", + "${StackName}-PatchUser", + {"label": "PatchUser"} ], [ "...", "${StackName}-PostContent", {"label": "PostContent"} ], + [ + "...", + "${StackName}-PostDonation", + {"label": "PostDonation"} + ], + [ + "...", + "${StackName}-PostDonationsReceipt", + {"label": "PostDonationsReceipt"} + ], [ "...", "${StackName}-PostDonor", @@ -1685,6 +1289,11 @@ Resources: "${StackName}-PostMessage", {"label": "PostMessage"} ], + [ + "...", + "${StackName}-PostNonprofit", + {"label": "PostNonprofit"} + ], [ "...", "${StackName}-PostNonprofitDonation", @@ -1695,6 +1304,11 @@ Resources: "${StackName}-PostNonprofitDonationTier", {"label": "PostNonprofitDonationTier"} ], + [ + "...", + "${StackName}-PostNonprofitReport", + {"label": "PostNonprofitReport"} + ], [ "...", "${StackName}-PostNonprofitSlide", @@ -1705,6 +1319,11 @@ Resources: "${StackName}-PostNonprofitUser", {"label": "PostNonprofitUser"} ], + [ + "...", + "${StackName}-PostPaymentTransaction", + {"label": "PostPaymentTransaction"} + ], [ "...", "${StackName}-PostReport", @@ -1735,6 +1354,26 @@ Resources: "${StackName}-ProcessDonations", {"label": "ProcessDonations"} ], + [ + "...", + "${StackName}-PutNonprofitSEO", + {"label": "PutNonprofitSEO"} + ], + [ + "...", + "${StackName}-PutNonprofitSocialSharing", + {"label": "PutNonprofitSocialSharing"} + ], + [ + "...", + "${StackName}-PutSEO", + {"label": "PutSEO"} + ], + [ + "...", + "${StackName}-PutSocialSharing", + {"label": "PutSocialSharing"} + ], [ "...", "${StackName}-RegisterNonprofit", @@ -1765,6 +1404,16 @@ Resources: "${StackName}-SearchNonprofits", {"label": "SearchNonprofits"} ], + [ + "...", + "${StackName}-SecurityHeadersAdminPages", + {"label": "SecurityHeadersAdminPages"} + ], + [ + "...", + "${StackName}-SecurityHeadersUploads", + {"label": "SecurityHeadersUploads"} + ], [ "...", "${StackName}-SendContactMessageEmail", @@ -1804,12 +1453,25 @@ Resources: "...", "${AWS::Region}.${StackName}-SecurityHeadersUploads", {"label": "SecurityHeadersUploads"} + ], + [ + "...", + "${StackName}-WarmSEO", + {"label": "WarmSEO"} + ], + [ + "...", + "${StackName}-WarmSocialSharing", + {"label": "WarmSocialSharing"} ] ], "view": "timeSeries", "stacked": false, "region": "${AWS::Region}", "title": "All Lambda Errors", + "legend": { + "position": "hidden" + }, "period": 300, "stat": "Sum" } @@ -1818,14 +1480,19 @@ Resources: "type": "metric", "x": 12, "y": 18, - "width": 12, + "width": 6, "height": 6, "properties": { "metrics": [ [ "AWS/Lambda", - "Duration", + "Errors", "FunctionName", + "${StackName}-AdminPostDonationsReceipt", + {"label": "AdminPostDonationsReceipt"} + ], + [ + "...", "${StackName}-AdminRegisterNonprofit", {"label": "AdminRegisterNonprofit"} ], @@ -1844,6 +1511,11 @@ Resources: "${StackName}-AuthorizeUsers", {"label": "AuthorizeUsers"} ], + [ + "...", + "${StackName}-BootstrapDatabase", + {"label": "BootstrapDatabase"} + ], [ "...", "${StackName}-CognitoCreateUser", @@ -1889,6 +1561,16 @@ Resources: "${StackName}-DeleteContents", {"label": "DeleteContents"} ], + [ + "...", + "${StackName}-DeleteDonation", + {"label": "DeleteDonation"} + ], + [ + "...", + "${StackName}-DeleteDonor", + {"label": "DeleteDonor"} + ], [ "...", "${StackName}-DeleteFile", @@ -1899,6 +1581,31 @@ Resources: "${StackName}-DeleteFiles", {"label": "DeleteFiles"} ], + [ + "...", + "${StackName}-DeleteMessage", + {"label": "DeleteMessage"} + ], + [ + "...", + "${StackName}-DeleteMetrics", + {"label": "DeleteMetrics"} + ], + [ + "...", + "${StackName}-DeleteNonprofit", + {"label": "DeleteNonprofit"} + ], + [ + "...", + "${StackName}-DeleteNonprofitDonation", + {"label": "DeleteNonprofitDonation"} + ], + [ + "...", + "${StackName}-DeleteNonprofitDonationTiers", + {"label": "DeleteNonprofitDonationTiers"} + ], [ "...", "${StackName}-DeleteNonprofitSlide", @@ -1909,21 +1616,51 @@ Resources: "${StackName}-DeleteNonprofitUser", {"label": "DeleteNonprofitUser"} ], + [ + "...", + "${StackName}-DeletePaymentTransaction", + {"label": "DeletePaymentTransaction"} + ], [ "...", "${StackName}-DeleteReports", {"label": "DeleteReports"} ], + [ + "...", + "${StackName}-DeleteSetting", + {"label": "DeleteSetting"} + ], [ "...", "${StackName}-DeleteSettings", {"label": "DeleteSettings"} ], + [ + "...", + "${StackName}-DeleteSponsor", + {"label": "DeleteSponsor"} + ], + [ + "...", + "${StackName}-DeleteSponsorTier", + {"label": "DeleteSponsorTier"} + ], + [ + "...", + "${StackName}-DeleteSponsors", + {"label": "DeleteSponsors"} + ], [ "...", "${StackName}-DeleteUser", {"label": "DeleteUser"} ], + [ + "...", + "${StackName}-DownloadFile", + {"label": "DownloadFile"} + ], [ "...", "${StackName}-GenerateCustomFrontendCss", @@ -1939,6 +1676,11 @@ Resources: "${StackName}-GenerateDynamicContent", {"label": "GenerateDynamicContent"} ], + [ + "...", + "${StackName}-GeneratePublicPagesHtml", + {"label": "GeneratePublicPagesHtml"} + ], [ "...", "${StackName}-GenerateReport", @@ -1949,11 +1691,31 @@ Resources: "${StackName}-GetContents", {"label": "GetContents"} ], + [ + "...", + "${StackName}-GetDonation", + {"label": "GetDonation"} + ], [ "...", "${StackName}-GetDonations", {"label": "GetDonations"} ], + [ + "...", + "${StackName}-GetDonationsReceipt", + {"label": "GetDonationsReceipt"} + ], + [ + "...", + "${StackName}-GetDonor", + {"label": "GetDonor"} + ], + [ + "...", + "${StackName}-GetDonors", + {"label": "GetDonors"} + ], [ "...", "${StackName}-GetEmail", @@ -1969,6 +1731,16 @@ Resources: "${StackName}-GetFiles", {"label": "GetFiles"} ], + [ + "...", + "${StackName}-GetMessage", + {"label": "GetMessage"} + ], + [ + "...", + "${StackName}-GetMessages", + {"label": "GetMessages"} + ], [ "...", "${StackName}-GetMetrics", @@ -1979,11 +1751,21 @@ Resources: "${StackName}-GetNonprofit", {"label": "GetNonprofit"} ], + [ + "...", + "${StackName}-GetNonprofitDonation", + {"label": "GetNonprofitDonation"} + ], [ "...", "${StackName}-GetNonprofitDonations", {"label": "GetNonprofitDonations"} ], + [ + "...", + "${StackName}-GetNonprofitDonationTier", + {"label": "GetNonprofitDonationTier"} + ], [ "...", "${StackName}-GetNonprofitDonationTiers", @@ -1994,6 +1776,11 @@ Resources: "${StackName}-GetNonprofitPage", {"label": "GetNonprofitPage"} ], + [ + "...", + "${StackName}-GetNonprofitReport", + {"label": "GetNonprofitReport"} + ], [ "...", "${StackName}-GetNonprofits", @@ -2014,6 +1801,16 @@ Resources: "${StackName}-GetNonprofitUsers", {"label": "GetNonprofitUsers"} ], + [ + "...", + "${StackName}-GetPaymentTransaction", + {"label": "GetPaymentTransaction"} + ], + [ + "...", + "${StackName}-GetPaymentTransactions", + {"label": "GetPaymentTransactions"} + ], [ "...", "${StackName}-GetReport", @@ -2079,16 +1876,46 @@ Resources: "${StackName}-MetricMaxAmount", {"label": "MetricMaxAmount"} ], + [ + "...", + "${StackName}-MigrateDatabase", + {"label": "MigrateDatabase"} + ], + [ + "...", + "${StackName}-PatchContent", + {"label": "PatchContent"} + ], [ "...", "${StackName}-PatchContents", {"label": "PatchContents"} ], + [ + "...", + "${StackName}-PatchDonation", + {"label": "PatchDonation"} + ], + [ + "...", + "${StackName}-PatchMessage", + {"label": "PatchMessage"} + ], + [ + "...", + "${StackName}-PatchMetrics", + {"label": "PatchMetrics"} + ], [ "...", "${StackName}-PatchNonprofit", {"label": "PatchNonprofit"} ], + [ + "...", + "${StackName}-PatchNonprofitDonation", + {"label": "PatchNonprofitDonation"} + ], [ "...", "${StackName}-PatchNonprofitDonationTiers", @@ -2109,6 +1936,11 @@ Resources: "${StackName}-PatchNonprofitStatus", {"label": "PatchNonprofitStatus"} ], + [ + "...", + "${StackName}-PatchPaymentTransaction", + {"label": "PatchPaymentTransaction"} + ], [ "...", "${StackName}-PatchSecureSetting", @@ -2144,6 +1976,11 @@ Resources: "${StackName}-PatchSponsorTier", {"label": "PatchSponsorTier"} ], + [ + "...", + "${StackName}-PatchSponsorTiers", + {"label": "PatchSponsorTiers"} + ], [ "...", "${StackName}-PatchUser", @@ -2154,6 +1991,16 @@ Resources: "${StackName}-PostContent", {"label": "PostContent"} ], + [ + "...", + "${StackName}-PostDonation", + {"label": "PostDonation"} + ], + [ + "...", + "${StackName}-PostDonationsReceipt", + {"label": "PostDonationsReceipt"} + ], [ "...", "${StackName}-PostDonor", @@ -2169,6 +2016,11 @@ Resources: "${StackName}-PostMessage", {"label": "PostMessage"} ], + [ + "...", + "${StackName}-PostNonprofit", + {"label": "PostNonprofit"} + ], [ "...", "${StackName}-PostNonprofitDonation", @@ -2179,6 +2031,11 @@ Resources: "${StackName}-PostNonprofitDonationTier", {"label": "PostNonprofitDonationTier"} ], + [ + "...", + "${StackName}-PostNonprofitReport", + {"label": "PostNonprofitReport"} + ], [ "...", "${StackName}-PostNonprofitSlide", @@ -2189,6 +2046,11 @@ Resources: "${StackName}-PostNonprofitUser", {"label": "PostNonprofitUser"} ], + [ + "...", + "${StackName}-PostPaymentTransaction", + {"label": "PostPaymentTransaction"} + ], [ "...", "${StackName}-PostReport", @@ -2219,6 +2081,26 @@ Resources: "${StackName}-ProcessDonations", {"label": "ProcessDonations"} ], + [ + "...", + "${StackName}-PutNonprofitSEO", + {"label": "PutNonprofitSEO"} + ], + [ + "...", + "${StackName}-PutNonprofitSocialSharing", + {"label": "PutNonprofitSocialSharing"} + ], + [ + "...", + "${StackName}-PutSEO", + {"label": "PutSEO"} + ], + [ + "...", + "${StackName}-PutSocialSharing", + {"label": "PutSocialSharing"} + ], [ "...", "${StackName}-RegisterNonprofit", @@ -2249,6 +2131,16 @@ Resources: "${StackName}-SearchNonprofits", {"label": "SearchNonprofits"} ], + [ + "...", + "${StackName}-SecurityHeadersAdminPages", + {"label": "SecurityHeadersAdminPages"} + ], + [ + "...", + "${StackName}-SecurityHeadersUploads", + {"label": "SecurityHeadersUploads"} + ], [ "...", "${StackName}-SendContactMessageEmail", @@ -2288,26 +2180,38 @@ Resources: "...", "${AWS::Region}.${StackName}-SecurityHeadersUploads", {"label": "SecurityHeadersUploads"} + ], + [ + "...", + "${StackName}-WarmSEO", + {"label": "WarmSEO"} + ], + [ + "...", + "${StackName}-WarmSocialSharing", + {"label": "WarmSocialSharing"} ] - ], "view": "timeSeries", "stacked": false, "region": "${AWS::Region}", - "title": "All Lambda Average Request Duration" + "title": "All Lambda Average Request Duration", + "legend": { + "position": "hidden" + } } }, { "type": "metric", - "x": 0, - "y": 24, + "x": 18, + "y": 18, "width": 6, - "height": 3, + "height": 6, "properties": { - "title": "Nonprofits Read Throttle", + "title": "Slow ProcessDonations", "annotations": { "alarms": [ - "${NonprofitsTableReadThrottleAlarm.Arn}" + "${processDonationsLambdaSlowAlarm.Arn}" ] }, "view": "timeSeries", @@ -2318,90 +2222,71 @@ Resources: { "type": "metric", "x": 0, - "y": 27, + "y": 24, "width": 6, - "height": 3, + "height": 6, "properties": { - "title": "Nonprofits Write Throttle", - "annotations": { - "alarms": [ - "${NonprofitsTableWriteThrottleAlarm.Arn}" + "metrics": [ + [ + "AWS/RDS", + "ServerlessDatabaseCapacity", + "DBClusterIdentifier", + "${DatabaseIdentifier}" ] - }, + ], "view": "timeSeries", "stacked": false, - "type": "chart" + "region": "${AWS::Region}", + "title": "RDS Capacity" } }, { "type": "metric", "x": 6, "y": 24, - "width": 9, + "width": 6, "height": 6, "properties": { + "title": "RDS CPU Utilization", + "annotations": { + "alarms": [ + "${rdsCpuUtilizationAlarm.Arn}" + ] + }, "view": "timeSeries", "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${NonprofitsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Nonprofits - Read" + "type": "chart" } }, { "type": "metric", - "x": 15, + "x": 12, "y": 24, - "width": 9, + "width": 6, "height": 6, "properties": { + "title": "RDS FreeLocalStorage Utilization", + "annotations": { + "alarms": [ + "${rdsFreeLocalStorageAlarm.Arn}" + ] + }, "view": "timeSeries", "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${NonprofitsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Nonprofits - Write" + "type": "chart" } }, { "type": "metric", - "x": 0, - "y": 30, + "x": 18, + "y": 24, "width": 6, - "height": 3, + "height": 6, "properties": { - "title": "NonprofitSlides Read Throttle", + "title": "RDS FreeableMemory Utilization", "annotations": { "alarms": [ - "${NonprofitSlidesTableReadThrottleAlarm.Arn}" + "${rdsFreeableMemoryAlarm.Arn}" ] }, "view": "timeSeries", @@ -2412,1301 +2297,190 @@ Resources: { "type": "metric", "x": 0, - "y": 33, - "width": 6, - "height": 3, - "properties": { - "title": "NonprofitSlides Write Throttle", - "annotations": { - "alarms": [ - "${NonprofitSlidesTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, "y": 30, - "width": 9, + "width": 12, "height": 6, "properties": { - "view": "timeSeries", - "stacked": false, "metrics": [ [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${NonprofitSlidesTable}", - {"label": "Provisioned"} + "AWS/RDS", + "InsertLatency", + "DBClusterIdentifier", + "${DatabaseIdentifier}" ], [ + "...", + "CommitLatency", ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "NonprofitSlides - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 30, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${NonprofitSlidesTable}", - {"label": "Provisioned"} + "." ], [ + "...", + "DeleteLatency", ".", - "ConsumedWriteCapacityUnits", + "." + ], + [ + "...", + "SelectLatency", ".", + "." + ], + [ + "...", + "UpdateLatency", ".", - {"label": "Consumed"} + "." ] ], - "region": "${AWS::Region}", - "title": "NonprofitSlides - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 36, - "width": 6, - "height": 3, - "properties": { - "title": "Donations Read Throttle", - "annotations": { - "alarms": [ - "${DonationsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 39, - "width": 6, - "height": 3, - "properties": { - "title": "Donations Write Throttle", - "annotations": { - "alarms": [ - "${DonationsTableWriteThrottleAlarm.Arn}" - ] - }, "view": "timeSeries", "stacked": false, - "type": "chart" + "region": "${AWS::Region}", + "title": "RDS Latency" } }, { "type": "metric", - "x": 6, - "y": 36, - "width": 9, + "x": 12, + "y": 30, + "width": 12, "height": 6, "properties": { - "view": "timeSeries", - "stacked": false, "metrics": [ [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${DonationsTable}", - {"label": "Provisioned"} + "AWS/RDS", + "InsertThroughput", + "DBClusterIdentifier", + "${DatabaseIdentifier}" ], [ + "...", + "CommitThroughput", ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Donations - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 36, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${DonationsTable}", - {"label": "Provisioned"} + "." ], [ + "...", + "DeleteThroughput", ".", - "ConsumedWriteCapacityUnits", + "." + ], + [ + "...", + "SelectThroughput", ".", + "." + ], + [ + "...", + "UpdateThroughput", ".", - {"label": "Consumed"} + "." ] ], - "region": "${AWS::Region}", - "title": "Donations - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 42, - "width": 6, - "height": 3, - "properties": { - "title": "Donors Read Throttle", - "annotations": { - "alarms": [ - "${DonorsTableReadThrottleAlarm.Arn}" - ] - }, "view": "timeSeries", "stacked": false, - "type": "chart" + "region": "${AWS::Region}", + "title": "RDS Throughput" } }, { "type": "metric", "x": 0, - "y": 45, - "width": 6, - "height": 3, - "properties": { - "title": "Donors Write Throttle", - "annotations": { - "alarms": [ - "${DonorsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 42, - "width": 9, + "y": 36, + "width": 12, "height": 6, "properties": { - "view": "timeSeries", - "stacked": false, "metrics": [ [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${DonorsTable}", - {"label": "Provisioned"} + "AWS/RDS", + "ConnectionAttempts", + "DBClusterIdentifier", + "${DatabaseIdentifier}" ], [ + "...", + "DatabaseConnections", ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Donors - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 42, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${DonorsTable}", - {"label": "Provisioned"} + "." ], [ + "...", + "Queries", ".", - "ConsumedWriteCapacityUnits", - ".", + "." + ], + [ + "...", + "ActiveTransactions", ".", - {"label": "Consumed"} + "." ] ], - "region": "${AWS::Region}", - "title": "Donors - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 48, - "width": 6, - "height": 3, - "properties": { - "title": "NonprofitDonationTiers Read Throttle", - "annotations": { - "alarms": [ - "${NonprofitDonationTiersTableReadThrottleAlarm.Arn}" - ] - }, "view": "timeSeries", "stacked": false, - "type": "chart" + "region": "${AWS::Region}", + "title": "RDS Connection Activity" } }, { "type": "metric", - "x": 0, - "y": 51, + "x": 12, + "y": 36, "width": 6, - "height": 3, - "properties": { - "title": "NonprofitDonationTiers Write Throttle", - "annotations": { - "alarms": [ - "${NonprofitDonationTiersTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 48, - "width": 9, "height": 6, "properties": { - "view": "timeSeries", - "stacked": false, "metrics": [ [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${NonprofitDonationTiersTable}", - {"label": "Provisioned"} + "AWS/RDS", + "BlockedTransactions", + "DBClusterIdentifier", + "${DatabaseIdentifier}" ], [ + "...", + "Deadlocks", ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "NonprofitDonationTiers - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 48, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${NonprofitDonationTiersTable}", - {"label": "Provisioned"} + "." ], [ + "...", + "AbortedClients", ".", - "ConsumedWriteCapacityUnits", - ".", + "." + ], + [ + "...", + "LoginFailures", ".", - {"label": "Consumed"} + "." ] ], + "view": "timeSeries", + "stacked": false, "region": "${AWS::Region}", - "title": "NonprofitDonationTiers - Write" + "title": "RDS Unexpected Activity" } }, { "type": "metric", - "x": 0, - "y": 54, + "x": 18, + "y": 36, "width": 6, - "height": 3, + "height": 6, "properties": { - "title": "Users Read Throttle", + "title": "SlowQueries", "annotations": { "alarms": [ - "${UsersTableReadThrottleAlarm.Arn}" + "${DbSlowQueryAlarm.Arn}" ] }, "view": "timeSeries", "stacked": false, "type": "chart" } - }, - { - "type": "metric", - "x": 0, - "y": 57, - "width": 6, - "height": 3, - "properties": { - "title": "Users Write Throttle", - "annotations": { - "alarms": [ - "${UsersTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 54, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${UsersTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Users - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 54, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${UsersTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Users - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 60, - "width": 6, - "height": 3, - "properties": { - "title": "Contents Read Throttle", - "annotations": { - "alarms": [ - "${ContentsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 63, - "width": 6, - "height": 3, - "properties": { - "title": "Contents Write Throttle", - "annotations": { - "alarms": [ - "${ContentsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 60, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${ContentsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Contents - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 60, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${ContentsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Contents - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 66, - "width": 6, - "height": 3, - "properties": { - "title": "Files Read Throttle", - "annotations": { - "alarms": [ - "${FilesTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 69, - "width": 6, - "height": 3, - "properties": { - "title": "Files Write Throttle", - "annotations": { - "alarms": [ - "${FilesTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 66, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${FilesTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Files - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 66, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${FilesTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Files - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 72, - "width": 6, - "height": 3, - "properties": { - "title": "Messages Read Throttle", - "annotations": { - "alarms": [ - "${MessagesTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 75, - "width": 6, - "height": 3, - "properties": { - "title": "Messages Write Throttle", - "annotations": { - "alarms": [ - "${MessagesTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 72, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${MessagesTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Messages - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 72, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${MessagesTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Messages - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 78, - "width": 6, - "height": 3, - "properties": { - "title": "Metrics Read Throttle", - "annotations": { - "alarms": [ - "${MetricsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 81, - "width": 6, - "height": 3, - "properties": { - "title": "Metrics Write Throttle", - "annotations": { - "alarms": [ - "${MetricsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 78, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${MetricsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Metrics - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 78, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${MetricsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Metrics - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 84, - "width": 6, - "height": 3, - "properties": { - "title": "PaymentTransactions Read Throttle", - "annotations": { - "alarms": [ - "${PaymentTransactionsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 87, - "width": 6, - "height": 3, - "properties": { - "title": "PaymentTransactions Write Throttle", - "annotations": { - "alarms": [ - "${PaymentTransactionsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 84, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${PaymentTransactionsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "PaymentTransactions - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 84, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${PaymentTransactionsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "PaymentTransactions - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 90, - "width": 6, - "height": 3, - "properties": { - "title": "Reports Read Throttle", - "annotations": { - "alarms": [ - "${ReportsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 93, - "width": 6, - "height": 3, - "properties": { - "title": "Reports Write Throttle", - "annotations": { - "alarms": [ - "${ReportsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 90, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${ReportsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Reports - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 90, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${ReportsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Reports - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 96, - "width": 6, - "height": 3, - "properties": { - "title": "Settings Read Throttle", - "annotations": { - "alarms": [ - "${SettingsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 99, - "width": 6, - "height": 3, - "properties": { - "title": "Settings Write Throttle", - "annotations": { - "alarms": [ - "${SettingsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 96, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${SettingsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Settings - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 96, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${SettingsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Settings - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 102, - "width": 6, - "height": 3, - "properties": { - "title": "Sponsors Read Throttle", - "annotations": { - "alarms": [ - "${SponsorsTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 105, - "width": 6, - "height": 3, - "properties": { - "title": "Sponsors Write Throttle", - "annotations": { - "alarms": [ - "${SponsorsTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 102, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${SponsorsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Sponsors - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 102, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${SponsorsTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "Sponsors - Write" - } - }, - { - "type": "metric", - "x": 0, - "y": 108, - "width": 6, - "height": 3, - "properties": { - "title": "SponsorTiers Read Throttle", - "annotations": { - "alarms": [ - "${SponsorTiersTableReadThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 0, - "y": 111, - "width": 6, - "height": 3, - "properties": { - "title": "SponsorTiers Write Throttle", - "annotations": { - "alarms": [ - "${SponsorTiersTableWriteThrottleAlarm.Arn}" - ] - }, - "view": "timeSeries", - "stacked": false, - "type": "chart" - } - }, - { - "type": "metric", - "x": 6, - "y": 108, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedReadCapacityUnits", - "TableName", - "${SponsorTiersTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedReadCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "SponsorTiers - Read" - } - }, - { - "type": "metric", - "x": 15, - "y": 108, - "width": 9, - "height": 6, - "properties": { - "view": "timeSeries", - "stacked": false, - "metrics": [ - [ - "AWS/DynamoDB", - "ProvisionedWriteCapacityUnits", - "TableName", - "${SponsorTiersTable}", - {"label": "Provisioned"} - ], - [ - ".", - "ConsumedWriteCapacityUnits", - ".", - ".", - {"label": "Consumed"} - ] - ], - "region": "${AWS::Region}", - "title": "SponsorTiers - Write" - } } ] } - - {} \ No newline at end of file + - {} + diff --git a/packages/cloudformation/templates/givesource-s3.yml b/packages/cloudformation/templates/givesource-s3.yml index 340219ca..8c31cd66 100644 --- a/packages/cloudformation/templates/givesource-s3.yml +++ b/packages/cloudformation/templates/givesource-s3.yml @@ -32,6 +32,15 @@ Resources: AdminPagesS3: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true WebsiteConfiguration: IndexDocument: index.html @@ -41,16 +50,33 @@ Resources: Bucket: !Ref AdminPagesS3 PolicyDocument: Statement: - - Effect: Allow - Action: - - s3:GetObject - Principal: "*" - Resource: !Sub |- - arn:aws:s3:::${AdminPagesS3}/* + - Sid: allow-ssl-requests-only + Effect: Deny + Principal: "*" + Action: s3:* + Resource: !Sub arn:aws:s3:::${AdminPagesS3}/* + Condition: + Bool: + aws:SecureTransport: false + - Sid: allow-cloudfront-access + Effect: Allow + Principal: + CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId + Action: s3:Get* + Resource: !Sub arn:aws:s3:::${AdminPagesS3}/* PublicPagesS3: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true WebsiteConfiguration: IndexDocument: index.html @@ -60,16 +86,33 @@ Resources: Bucket: !Ref PublicPagesS3 PolicyDocument: Statement: - - Effect: Allow - Action: - - s3:GetObject - Principal: "*" - Resource: !Sub |- - arn:aws:s3:::${PublicPagesS3}/* + - Sid: allow-ssl-requests-only + Effect: Deny + Principal: "*" + Action: s3:* + Resource: !Sub arn:aws:s3:::${PublicPagesS3}/* + Condition: + Bool: + aws:SecureTransport: false + - Sid: allow-cloudfront-access + Effect: Allow + Principal: + CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId + Action: s3:Get* + Resource: !Sub arn:aws:s3:::${PublicPagesS3}/* UploadsS3: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true CorsConfiguration: CorsRules: - AllowedMethods: @@ -90,12 +133,97 @@ Resources: Bucket: !Ref UploadsS3 PolicyDocument: Statement: - - Effect: Allow - Action: - - s3:GetObject - Principal: "*" - Resource: !Sub |- - arn:aws:s3:::${UploadsS3}/* + - Sid: allow-ssl-requests-only + Effect: Deny + Principal: "*" + Action: s3:* + Resource: !Sub arn:aws:s3:::${UploadsS3}/* + Condition: + Bool: + aws:SecureTransport: false + - Sid: allow-cloudfront-access + Effect: Allow + Principal: + CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId + Action: s3:Get* + Resource: !Sub arn:aws:s3:::${UploadsS3}/* + + Reports: + Type: AWS::S3::Bucket + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + LoggingConfiguration: + DestinationBucketName: !ImportValue AccessLoggingBucket + LogFilePrefix: !Sub reports-${AWS::StackName}/ + + ReportsBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref Reports + PolicyDocument: + Statement: + - Sid: allow-ssl-requests-only + Effect: Deny + Principal: '*' + Action: s3:* + Resource: !Sub arn:aws:s3:::${Reports}/* + Condition: + Bool: + aws:SecureTransport: false + + GivesourceCache: + Type: AWS::S3::Bucket + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + CorsConfiguration: + CorsRules: + - AllowedMethods: + - GET + - PUT + - DELETE + AllowedOrigins: + - "*" + AllowedHeaders: + - "*" + WebsiteConfiguration: + IndexDocument: index.html + + GivesourceCacheBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref GivesourceCache + PolicyDocument: + Statement: + - Sid: allow-ssl-requests-only + Effect: Deny + Principal: "*" + Action: s3:* + Resource: !Sub arn:aws:s3:::${GivesourceCache}/* + Condition: + Bool: + aws:SecureTransport: false + - Sid: allow-cloudfront-access + Effect: Allow + Principal: + CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId + Action: s3:Get* + Resource: !Sub arn:aws:s3:::${GivesourceCache}/* # AWS CloudFront Resources @@ -105,11 +233,10 @@ Resources: DistributionConfig: Aliases: !If [HasAdminPagesCNAMEs, !Ref AdminPagesCNAMEs, !Ref "AWS::NoValue"] Origins: - - DomainName: - !Select [ 2, !Split [ /, !GetAtt AdminPagesS3.WebsiteURL ] ] + - DomainName: !GetAtt AdminPagesS3.DomainName Id: !Ref AdminPagesS3 - CustomOriginConfig: - OriginProtocolPolicy: http-only + S3OriginConfig: + OriginAccessIdentity: !Join ['', ['origin-access-identity/cloudfront/', !Ref CloudFrontOAI]] Enabled: true Comment: Distribution for Givsource admin pages S3 bucket DefaultRootObject: index.html @@ -132,6 +259,10 @@ Resources: ErrorCode: 404 ResponseCode: 200 ResponsePagePath: /index.html + - ErrorCachingMinTTL: 0 + ErrorCode: 403 + ResponseCode: 200 + ResponsePagePath: /index.html DependsOn: AdminPagesS3 PublicPagesDistribution: @@ -140,11 +271,10 @@ Resources: DistributionConfig: Aliases: !If [HasPublicPagesCNAMEs, !Ref PublicPagesCNAMEs, !Ref "AWS::NoValue"] Origins: - - DomainName: - !Select [ 2, !Split [ /, !GetAtt PublicPagesS3.WebsiteURL ] ] - Id: !Ref PublicPagesS3 - CustomOriginConfig: - OriginProtocolPolicy: http-only + - Id: !Ref PublicPagesS3 + DomainName: !GetAtt PublicPagesS3.DomainName + S3OriginConfig: + OriginAccessIdentity: !Join ['', ['origin-access-identity/cloudfront/', !Ref CloudFrontOAI]] Enabled: true Comment: Distribution for Givesource(R) public pages S3 bucket DefaultRootObject: index.html @@ -169,6 +299,10 @@ Resources: ErrorCode: 404 ResponseCode: 200 ResponsePagePath: /index.html + - ErrorCachingMinTTL: 0 + ErrorCode: 403 + ResponseCode: 200 + ResponsePagePath: /index.html DependsOn: PublicPagesS3 UploadsDistribution: @@ -176,11 +310,10 @@ Resources: Properties: DistributionConfig: Origins: - - DomainName: - !Select [ 2, !Split [ /, !GetAtt UploadsS3.WebsiteURL ] ] - Id: !Ref UploadsS3 - CustomOriginConfig: - OriginProtocolPolicy: http-only + - DomainName: !GetAtt UploadsS3.DomainName + Id: !Ref UploadsS3 + S3OriginConfig: + OriginAccessIdentity: !Join ['', ['origin-access-identity/cloudfront/', !Ref CloudFrontOAI]] Enabled: true Comment: Distribution for Givesource(R) uploads S3 bucket DefaultRootObject: index.html @@ -200,8 +333,49 @@ Resources: ErrorCode: 404 ResponseCode: 200 ResponsePagePath: /index.html + - ErrorCachingMinTTL: 0 + ErrorCode: 403 + ResponseCode: 200 + ResponsePagePath: /index.html DependsOn: UploadsS3 + CloudFrontOAI: + Type: AWS::CloudFront::CloudFrontOriginAccessIdentity + Properties: + CloudFrontOriginAccessIdentityConfig: + Comment: !Ref UploadsS3 + + CachingDistribution: + Type: AWS::CloudFront::Distribution + Properties: + DistributionConfig: + Origins: + - DomainName: !GetAtt GivesourceCache.DomainName + Id: !Ref GivesourceCache + S3OriginConfig: + OriginAccessIdentity: !Join ['', ['origin-access-identity/cloudfront/', !Ref CloudFrontOAI]] + Enabled: true + Comment: Distribution for Givesource(R) caching S3 bucket + DefaultRootObject: index.html + DefaultCacheBehavior: + DefaultTTL: 0 + ForwardedValues: + QueryString: false + Cookies: + Forward: none + TargetOriginId: !Ref GivesourceCache + ViewerProtocolPolicy: allow-all + PriceClass: PriceClass_200 + ViewerCertificate: + CloudFrontDefaultCertificate: true + CustomErrorResponses: + - ErrorCachingMinTTL: 0 + ErrorCode: 404 + ResponseCode: 200 + ResponsePagePath: /index.html + DependsOn: GivesourceCache + + Outputs: AdminPagesCloudFrontDistribution: @@ -250,4 +424,26 @@ Outputs: Value: !Ref UploadsS3 UploadsS3BucketUrl: - Value: !GetAtt UploadsS3.WebsiteURL \ No newline at end of file + Value: !GetAtt UploadsS3.WebsiteURL + + CachingCloudFrontDistribution: + Value: !Ref CachingDistribution + + CachingCloudFrontDomainName: + Value: !GetAtt CachingDistribution.DomainName + + CachingCloudFrontUrl: + Value: !Sub |- + https://${CachingDistribution.DomainName} + + GivesourceCache: + Value: !Ref GivesourceCache + + GivesourceCacheBucketUrl: + Value: !GetAtt GivesourceCache.WebsiteURL + + Reports: + Value: !Ref Reports + + ReportsBucketUrl: + Value: !GetAtt Reports.WebsiteURL diff --git a/packages/cloudformation/templates/givesource.yml b/packages/cloudformation/templates/givesource.yml index a0912b34..442d358f 100644 --- a/packages/cloudformation/templates/givesource.yml +++ b/packages/cloudformation/templates/givesource.yml @@ -1,4 +1,4 @@ ---- + AWSTemplateFormatVersion: 2010-09-09 Description: AWS Resources for Givesource(R) Parameters: @@ -33,6 +33,11 @@ Parameters: Type: String Default: "false" + ReplicaRegion: + Description: The region where this stack will be replicated + Type: String + Default: "" + Mappings: ApiGateway: IntegrationRequestTemplate: @@ -91,16 +96,31 @@ Conditions: EnableMonitoring: !Equals ["true", !Ref EnableMonitoring] -Resources: + IsReplicaRegion: !Equals [!Ref "AWS::Region", !Ref ReplicaRegion] - DynamoDbStack: + NotReplicaRegion: !Not [!Equals [!Ref "AWS::Region", !Ref ReplicaRegion]] + +Resources: + AuroraDbStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName - TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-dynamo.yml + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId + LambdaRole: !Ref LambdaRole + SecureLambdaRole: !Ref SecureLambdaRole + TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora.yml TimeoutInMinutes: 40 + AuroraDbSnapshotCopyStack: + Condition: IsReplicaRegion + Type: AWS::CloudFormation::Stack + Properties: + Parameters: + StackName: !Ref AWS::StackName + TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-aurora-snapshot-copy.yml + S3Stack: Type: AWS::CloudFormation::Stack Properties: @@ -118,6 +138,83 @@ Resources: Name: !Sub |- ${AWS::StackName} + ApiCachePolicy: + Type: AWS::CloudFront::CachePolicy + Properties: + CachePolicyConfig: + Comment: Policy for long lived caching with Givesource settings, contents, and files + DefaultTTL: 86400 + MaxTTL: 31536000 + MinTTL: 1 + Name: !Sub ${AWS::StackName}-Givesource-CachePolicy-${AWS::Region} + ParametersInCacheKeyAndForwardedToOrigin: + CookiesConfig: + CookieBehavior: none + EnableAcceptEncodingGzip: true + HeadersConfig: + HeaderBehavior: whitelist + Headers: ["Authorization"] + QueryStringsConfig: + QueryStringBehavior: all + DependsOn: RestApi + + NoCachePolicy: + Type: AWS::CloudFront::CachePolicy + Properties: + CachePolicyConfig: + Comment: Policy for no caching with authorized headers for the admin area + DefaultTTL: 0 + MaxTTL: 30 + MinTTL: 0 + Name: !Sub ${AWS::StackName}-Givesource-NoCachePolicy-${AWS::Region} + ParametersInCacheKeyAndForwardedToOrigin: + CookiesConfig: + CookieBehavior: none + EnableAcceptEncodingGzip: true + HeadersConfig: + HeaderBehavior: whitelist + Headers: ["Authorization"] + QueryStringsConfig: + QueryStringBehavior: all + DependsOn: RestApi + + ApiDistribution: + Type: AWS::CloudFront::Distribution + Properties: + DistributionConfig: + Origins: + - Id: !Ref RestApi + DomainName: !Sub ${RestApi}.execute-api.${AWS::Region}.amazonaws.com + OriginPath: "/prod" + CustomOriginConfig: + OriginSSLProtocols: ["TLSv1.2"] + OriginProtocolPolicy: "https-only" + Enabled: true + Comment: Distribution for Givesource(R) api caching + DefaultRootObject: index.html + DefaultCacheBehavior: + AllowedMethods: ["GET", "HEAD", "OPTIONS", "PUT", "PATCH", "POST", "DELETE"] + CachePolicyId: !GetAtt NoCachePolicy.Id + TargetOriginId: !Ref RestApi + ViewerProtocolPolicy: redirect-to-https + PriceClass: PriceClass_200 + CacheBehaviors: + - PathPattern: "/settings" + AllowedMethods: ["GET", "HEAD", "OPTIONS", "PUT", "PATCH", "POST", "DELETE"] + CachePolicyId: !GetAtt ApiCachePolicy.Id + TargetOriginId: !Ref RestApi + ViewerProtocolPolicy: redirect-to-https + - PathPattern: "/contents" + AllowedMethods: ["GET", "HEAD", "OPTIONS", "PUT", "PATCH", "POST", "DELETE"] + CachePolicyId: !GetAtt ApiCachePolicy.Id + TargetOriginId: !Ref RestApi + ViewerProtocolPolicy: redirect-to-https + - PathPattern: "/files" + AllowedMethods: ["GET", "HEAD", "OPTIONS", "PUT", "PATCH", "POST", "DELETE"] + CachePolicyId: !GetAtt ApiCachePolicy.Id + TargetOriginId: !Ref RestApi + ViewerProtocolPolicy: redirect-to-https + ApiGatewayManagedPolicy: Type: AWS::IAM::ManagedPolicy Properties: @@ -143,6 +240,16 @@ Resources: Action: cloudformation:DescribeStacks Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${AWS::StackName}/* + CloudFrontManagedPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: cloudfront:CreateInvalidation + Resource: !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${ApiDistribution} + CloudWatchLogsManagedPolicy: Type: AWS::IAM::ManagedPolicy Properties: @@ -168,47 +275,6 @@ Resources: - iam:PassRole Resource: '*' - DynamoDbManagedPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: dynamodb:* - Resource: - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.ContentsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.ContentsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.DonationsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.DonationsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.DonorsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.DonorsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.FilesTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.FilesTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.MessagesTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.MessagesTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.MetricsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.MetricsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.NonprofitsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.NonprofitsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.NonprofitDonationTiersTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.NonprofitDonationTiersTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.NonprofitSlidesTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.NonprofitSlidesTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.PaymentTransactionsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.PaymentTransactionsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.ReportsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.ReportsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.SettingsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.SettingsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.SponsorsTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.SponsorsTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.SponsorTiersTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.SponsorTiersTable}/index/* - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.UsersTable} - - !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDbStack.Outputs.UsersTable}/index/* - DependsOn: DynamoDbStack - LambdaManagedPolicy: Type: AWS::IAM::ManagedPolicy Properties: @@ -231,6 +297,8 @@ Resources: - !Sub arn:aws:s3:::${S3Stack.Outputs.AdminPagesS3} - !Sub arn:aws:s3:::${S3Stack.Outputs.PublicPagesS3} - !Sub arn:aws:s3:::${S3Stack.Outputs.UploadsS3} + - !Sub arn:aws:s3:::${S3Stack.Outputs.GivesourceCache} + - !Sub arn:aws:s3:::${S3Stack.Outputs.Reports} - arn:aws:s3:::{{awsReleaseBucket}} - Effect: Allow Action: s3:Get* @@ -238,6 +306,8 @@ Resources: - !Sub arn:aws:s3:::${S3Stack.Outputs.AdminPagesS3}/* - !Sub arn:aws:s3:::${S3Stack.Outputs.PublicPagesS3}/* - !Sub arn:aws:s3:::${S3Stack.Outputs.UploadsS3}/* + - !Sub arn:aws:s3:::${S3Stack.Outputs.GivesourceCache}/* + - !Sub arn:aws:s3:::${S3Stack.Outputs.Reports}/* - arn:aws:s3:::{{awsReleaseBucket}}/* - Effect: Allow Action: @@ -247,6 +317,8 @@ Resources: - !Sub arn:aws:s3:::${S3Stack.Outputs.AdminPagesS3}/* - !Sub arn:aws:s3:::${S3Stack.Outputs.PublicPagesS3}/* - !Sub arn:aws:s3:::${S3Stack.Outputs.UploadsS3}/* + - !Sub arn:aws:s3:::${S3Stack.Outputs.GivesourceCache}/* + - !Sub arn:aws:s3:::${S3Stack.Outputs.Reports}/* SESManagedPolicy: Type: AWS::IAM::ManagedPolicy @@ -306,23 +378,41 @@ Resources: - lambda.amazonaws.com - edgelambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref ApiGatewayManagedPolicy - !Ref CloudFormationManagedPolicy + - !Ref CloudFrontManagedPolicy - !Ref CloudWatchLogsManagedPolicy - !Ref CognitoManagedPolicy - - !Ref DynamoDbManagedPolicy - !Ref LambdaManagedPolicy - !Ref S3ManagedPolicy - !Ref SESManagedPolicy - !Ref SSMManagedPolicy + LambdaSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Ingress/egress rules for lambda + VpcId: !ImportValue givesource-vpc + SecurityGroupIngress: [] + SecurityGroupEgress: [] + Tags: + - Key: Name + Value: givesource-lambda + CustomStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName + ApiDistributionId: !Ref ApiDistribution + ApiDistributionUrl: !Join ["", ["https://", !GetAtt ApiDistribution.DomainName, "/"]] RestApi: !Ref RestApi LambdaRoleArn: !GetAtt LambdaRole.Arn + SecureLambdaRole: !Ref SecureLambdaRole + SecureSettingsLambdaFunctionRole: !Ref SecureSettingsLambdaFunctionRole + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] CognitoSnsCallerRoleArn: !GetAtt CognitoSnsCallerRole.Arn AdminPagesS3: !GetAtt S3Stack.Outputs.AdminPagesS3 @@ -334,35 +424,13 @@ Resources: UploadsS3: !GetAtt S3Stack.Outputs.UploadsS3 UploadsCloudFrontDistribution: !GetAtt S3Stack.Outputs.UploadsCloudFrontDistribution UploadsCloudFrontUrl: !GetAtt S3Stack.Outputs.UploadsCloudFrontUrl + GivesourceCache: !GetAtt S3Stack.Outputs.GivesourceCache + CachingCloudFrontUrl: !GetAtt S3Stack.Outputs.CachingCloudFrontUrl + ReportsS3: !GetAtt S3Stack.Outputs.Reports TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-custom.yml TimeoutInMinutes: 20 DependsOn: - - CognitoSnsCallerRole - - DynamoDbStack - - LambdaRole - - S3Stack - - SecureSettingsEncryptManagedPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: kms:Encrypt - Resource: !GetAtt CustomStack.Outputs.SecureSettingsKeyArn - DependsOn: CustomStack - - SecureSettingsDecryptManagedPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: kms:Decrypt - Resource: !GetAtt CustomStack.Outputs.SecureSettingsKeyArn - DependsOn: CustomStack + - AuroraDbStack SecureSettingsLambdaFunctionRole: Type: AWS::IAM::Role @@ -375,10 +443,9 @@ Resources: Service: - lambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref CloudWatchLogsManagedPolicy - !Ref SSMManagedPolicy - - !Ref SecureSettingsEncryptManagedPolicy - DependsOn: SecureSettingsEncryptManagedPolicy SecureLambdaRole: Type: AWS::IAM::Role @@ -391,23 +458,24 @@ Resources: Service: - lambda.amazonaws.com ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - !Ref ApiGatewayManagedPolicy - !Ref CloudFormationManagedPolicy - !Ref CloudWatchLogsManagedPolicy - !Ref CognitoManagedPolicy - - !Ref DynamoDbManagedPolicy - !Ref SSMManagedPolicy - !Ref LambdaManagedPolicy - !Ref S3ManagedPolicy - !Ref SESManagedPolicy - - !Ref SecureSettingsDecryptManagedPolicy ApiContentsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -418,16 +486,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-contents.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiDonationsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId SecureLambdaRoleArn: !GetAtt SecureLambdaRole.Arn DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] @@ -439,16 +507,17 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-donations.yml TimeoutInMinutes: 20 DependsOn: + - AuroraDbStack - CustomStack - - LambdaRole - - RestApi ApiDonorsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -459,16 +528,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-donors.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiFilesStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -476,21 +545,21 @@ Resources: RestApi: !Ref RestApi RestApiRootResourceId: !GetAtt RestApi.RootResourceId UploadsBucket: !GetAtt S3Stack.Outputs.UploadsS3 + ReportsBucket: !GetAtt S3Stack.Outputs.Reports AuthorizeUsers: !GetAtt CustomStack.Outputs.AuthorizeUsers TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-files.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi - - S3Stack + - AuroraDbStack ApiMessagesStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -501,16 +570,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-messages.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiMetricsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -521,16 +590,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-metrics.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiNonprofitsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -543,16 +612,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-nonprofits.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiPaymentTransactionsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -563,16 +632,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-payment-transactions.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiReportsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -584,16 +653,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-reports.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiSettingsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -609,16 +678,17 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-settings.yml TimeoutInMinutes: 20 DependsOn: + - AuroraDbStack - CustomStack - - LambdaRole - - RestApi ApiSponsorsStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -629,16 +699,16 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-sponsors.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiUsersStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: StackName: !Ref AWS::StackName LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] IntegrationRequestTemplate: !FindInMap [ApiGateway, IntegrationRequestTemplate, Default] IntegrationResponsesTemplate: !FindInMap [ApiGateway, IntegrationResponsesTemplate, Default] @@ -650,11 +720,10 @@ Resources: TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-api-users.yml TimeoutInMinutes: 20 DependsOn: - - CustomStack - - LambdaRole - - RestApi + - AuroraDbStack ApiDeployStack: + Condition: NotReplicaRegion Type: AWS::CloudFormation::Stack Properties: Parameters: @@ -677,6 +746,7 @@ Resources: - RestApi CognitoInitialUser: + Condition: NotReplicaRegion Type: Custom::CognitoSuperAdminUser Properties: ServiceToken: !GetAtt CustomStack.Outputs.CognitoCreateUserFunctionArn @@ -685,7 +755,7 @@ Resources: DependsOn: - ApiDeployStack - CustomStack - - DynamoDbStack + - AuroraDbStack - S3Stack MonitoringStack: @@ -701,26 +771,27 @@ Resources: PublicPagesCloudFrontDomainName: !GetAtt S3Stack.Outputs.PublicPagesCloudFrontDomainName PublicPagesCloudFrontDistribution: !GetAtt S3Stack.Outputs.PublicPagesCloudFrontDistribution PublicPagesCNAMEs: !Join [",", !Ref PublicPagesCNAMEs] - ContentsTable: !GetAtt DynamoDbStack.Outputs.ContentsTable - DonationsTable: !GetAtt DynamoDbStack.Outputs.DonationsTable - DonorsTable: !GetAtt DynamoDbStack.Outputs.DonorsTable - FilesTable: !GetAtt DynamoDbStack.Outputs.FilesTable - MessagesTable: !GetAtt DynamoDbStack.Outputs.MessagesTable - MetricsTable: !GetAtt DynamoDbStack.Outputs.MetricsTable - NonprofitsTable: !GetAtt DynamoDbStack.Outputs.NonprofitsTable - NonprofitDonationTiersTable: !GetAtt DynamoDbStack.Outputs.NonprofitDonationTiersTable - NonprofitSlidesTable: !GetAtt DynamoDbStack.Outputs.NonprofitSlidesTable - PaymentTransactionsTable: !GetAtt DynamoDbStack.Outputs.PaymentTransactionsTable - ReportsTable: !GetAtt DynamoDbStack.Outputs.ReportsTable - SettingsTable: !GetAtt DynamoDbStack.Outputs.SettingsTable - SponsorsTable: !GetAtt DynamoDbStack.Outputs.SponsorsTable - SponsorTiersTable: !GetAtt DynamoDbStack.Outputs.SponsorTiersTable - UsersTable: !GetAtt DynamoDbStack.Outputs.UsersTable + DatabaseIdentifier: !GetAtt AuroraDbStack.Outputs.Identifier TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-monitoring.yml TimeoutInMinutes: 20 DependsOn: - CognitoInitialUser + CacheStack: + Condition: NotReplicaRegion + Type: AWS::CloudFormation::Stack + Properties: + Parameters: + StackName: !Ref AWS::StackName + LambdaRoleArn: !GetAtt LambdaRole.Arn + LambdaSecurityGroupId: !GetAtt LambdaSecurityGroup.GroupId + DefaultLambdaFunctionTimeout: !FindInMap [Lambda, Timeout, Default] + CacheS3: !GetAtt S3Stack.Outputs.GivesourceCache + TemplateURL: https://s3.{{awsReleaseBucketRegion}}.amazonaws.com/{{awsReleaseBucket}}/cf-templates/{{version}}/givesource-cache.yml + TimeoutInMinutes: 40 + DependsOn: + - AuroraDbStack + Outputs: AdminPagesCloudFrontDistribution: @@ -737,7 +808,7 @@ Outputs: ApiUrl: Value: !Sub |- - https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/ + https://${ApiDistribution.DomainName}/ LambdaRoleArn: Value: !GetAtt LambdaRole.Arn @@ -767,10 +838,12 @@ Outputs: Value: !GetAtt S3Stack.Outputs.UploadsS3BucketUrl UserPoolClientId: + Condition: NotReplicaRegion Value: !GetAtt CustomStack.Outputs.CognitoUserPoolClientId UserPoolId: + Condition: NotReplicaRegion Value: !GetAtt CustomStack.Outputs.CognitoUserPoolId Version: - Value: {{version}} \ No newline at end of file + Value: {{version}} diff --git a/packages/frontend/bin/aws/cloudFormation.js b/packages/frontend/bin/aws/cloudFormation.js index 5619f820..3df03b36 100644 --- a/packages/frontend/bin/aws/cloudFormation.js +++ b/packages/frontend/bin/aws/cloudFormation.js @@ -34,29 +34,31 @@ function CloudFormation() { * @return {Promise} */ CloudFormation.prototype.describeStacks = (region, stackName, nextToken, stacks) => { - const cloudFormation = this; - const awsCloudFormation = new AWS.CloudFormation({region: region}); - return new Promise((resolve, reject) => { - stacks = stacks || []; - const params = {}; - if (stackName) { - params.StackName = stackName; - } - if (nextToken) { - params.NextToken = nextToken; - } - awsCloudFormation.describeStacks(params, (err, data) => { - if (err) { - reject(err); - } - stacks = stacks.concat(data.Stacks); - if (data.NextToken) { - resolve(cloudFormation.describeStacks(region, stackName, data.nextToken, stacks)); - } else { - resolve(stacks); - } - }); - }); + const cloudFormation = this; + const awsCloudFormation = new AWS.CloudFormation({region: region}); + return new Promise((resolve, reject) => { + stacks = stacks || []; + const params = {}; + if (stackName) { + params.StackName = stackName; + } + if (nextToken) { + params.NextToken = nextToken; + } + awsCloudFormation.describeStacks(params, (err, data) => { + if (err) { + reject(err); + return; + } + + stacks = stacks.concat(data.Stacks); + if (data.NextToken) { + resolve(cloudFormation.describeStacks(region, stackName, data.nextToken, stacks)); + } else { + resolve(stacks); + } + }); + }); }; -module.exports = CloudFormation; \ No newline at end of file +module.exports = CloudFormation; diff --git a/packages/frontend/bin/fetch-settings.js b/packages/frontend/bin/fetch-settings.js index a01e4627..b7822830 100755 --- a/packages/frontend/bin/fetch-settings.js +++ b/packages/frontend/bin/fetch-settings.js @@ -32,12 +32,12 @@ const fs = require('fs'); * @return {*} */ const findOutputKey = (outputs, outputKey) => { - const output = _.find(outputs, {OutputKey: outputKey}); - if (output && output.OutputValue) { - return output.OutputValue; - } else { - throw new Error(outputKey + ' not found'); - } + const output = _.find(outputs, {OutputKey: outputKey}); + if (output && output.OutputValue) { + return output.OutputValue; + } else { + throw new Error(outputKey + ' not found'); + } }; /** @@ -46,24 +46,27 @@ const findOutputKey = (outputs, outputKey) => { * @return {Promise} */ const getSettings = () => { - const cloudFormation = new CloudFormation(); - return cloudFormation.describeStacks(config.get('stack.AWS_REGION'), config.get('stack.AWS_STACK_NAME')).then(stacks => { - if (stacks.length !== 1) { - return Promise.reject(new Error('unexpected number of stacks')); - } else { - const stack = stacks[0]; - return Promise.resolve({ - API_URL: findOutputKey(stack.Outputs, 'ApiUrl'), - AdminPagesCloudFrontDistribution: findOutputKey(stack.Outputs, 'AdminPagesCloudFrontDistribution'), - AdminPagesS3BucketName: findOutputKey(stack.Outputs, 'AdminPagesS3BucketName'), - AdminPagesS3BucketUrl: findOutputKey(stack.Outputs, 'AdminPagesS3BucketUrl'), - PublicPagesCloudFrontDistribution: findOutputKey(stack.Outputs, 'PublicPagesCloudFrontDistribution'), - PublicPagesS3BucketName: findOutputKey(stack.Outputs, 'PublicPagesS3BucketName'), - PublicPagesS3BucketUrl: findOutputKey(stack.Outputs, 'PublicPagesS3BucketUrl'), - UploadsCloudFrontDistribution: findOutputKey(stack.Outputs, 'UploadsCloudFrontDistribution'), - }); - } - }); + const cloudFormation = new CloudFormation(); + return cloudFormation.describeStacks(config.get('stack.AWS_REGION'), config.get('stack.AWS_STACK_NAME')).then(stacks => { + if (stacks.length !== 1) { + return Promise.reject(new Error('unexpected number of stacks')); + } else { + const stack = stacks[0]; + return Promise.resolve({ + API_URL: findOutputKey(stack.Outputs, 'ApiUrl'), + AdminPagesCloudFrontDistribution: findOutputKey(stack.Outputs, 'AdminPagesCloudFrontDistribution'), + AdminPagesS3BucketName: findOutputKey(stack.Outputs, 'AdminPagesS3BucketName'), + AdminPagesS3BucketUrl: findOutputKey(stack.Outputs, 'AdminPagesS3BucketUrl'), + PublicPagesCloudFrontDistribution: findOutputKey(stack.Outputs, 'PublicPagesCloudFrontDistribution'), + PublicPagesS3BucketName: findOutputKey(stack.Outputs, 'PublicPagesS3BucketName'), + PublicPagesS3BucketUrl: findOutputKey(stack.Outputs, 'PublicPagesS3BucketUrl'), + UploadsCloudFrontDistribution: findOutputKey(stack.Outputs, 'UploadsCloudFrontDistribution'), + }); + } + }).catch(err => { + // This can happen when the app hasn't been created yet - so continue instead of erroring + return {}; + }); }; /** @@ -73,36 +76,36 @@ const getSettings = () => { * @param {{}} data */ const writeConfig = (filename, data) => { - const jsonData = JSON.stringify(data, null, 2); - const filePath = path.resolve(__dirname, './../config/' + filename); - fs.writeFileSync(filePath, jsonData); - console.log(filename + ' created'); + const jsonData = JSON.stringify(data, null, 2); + const filePath = path.resolve(__dirname, './../config/' + filename); + fs.writeFileSync(filePath, jsonData); + console.log(filename + ' created'); }; getSettings().then(data => { - const settings = { - API_URL: null - }; - const deployInfo = { - AdminPagesCloudFrontDistribution: null, - AdminPagesS3BucketName: null, - AdminPagesS3BucketUrl: null, - PublicPagesCloudFrontDistribution: null, - PublicPagesS3BucketName: null, - PublicPagesS3BucketUrl: null, - UploadsCloudFrontDistribution: null, - }; - Object.keys(data).forEach(key => { - if (settings.hasOwnProperty(key)) { - settings[key] = data[key]; - } - if (deployInfo.hasOwnProperty(key)) { - deployInfo[key] = data[key]; - } - }); + const settings = { + API_URL: null + }; + const deployInfo = { + AdminPagesCloudFrontDistribution: null, + AdminPagesS3BucketName: null, + AdminPagesS3BucketUrl: null, + PublicPagesCloudFrontDistribution: null, + PublicPagesS3BucketName: null, + PublicPagesS3BucketUrl: null, + UploadsCloudFrontDistribution: null, + }; + Object.keys(data).forEach(key => { + if (settings.hasOwnProperty(key)) { + settings[key] = data[key]; + } + if (deployInfo.hasOwnProperty(key)) { + deployInfo[key] = data[key]; + } + }); - writeConfig('settings.json', settings); - writeConfig('deploy-info.json', deployInfo); + writeConfig('settings.json', settings); + writeConfig('deploy-info.json', deployInfo); }).catch(err => { - console.log(err); -}); \ No newline at end of file + console.log(err); +}); diff --git a/packages/frontend/src/admin-pages/components/account/UserAccount.vue b/packages/frontend/src/admin-pages/components/account/UserAccount.vue index 2e3f3fbf..c4f7d482 100644 --- a/packages/frontend/src/admin-pages/components/account/UserAccount.vue +++ b/packages/frontend/src/admin-pages/components/account/UserAccount.vue @@ -16,7 +16,7 @@ @@ -70,6 +70,7 @@ return { firstName: this.user.firstName, lastName: this.user.lastName, + email: this.user.email, gravatarAlt: this.user.firstName && this.user.lastName ? this.user.firstName + ' ' + this.user.lastName : 'Avatar', navigationComponent: 'navigation-nonprofit', @@ -82,14 +83,14 @@ return this.isSuperAdminUser() || this.isAdminUser(); }, logoLink: function () { - if (!this.isAdmin && this.nonprofitUuid) { - return {name: 'nonprofit-donations-list', params: {nonprofitUuid: this.nonprofitUuid}}; + if (!this.isAdmin && this.nonprofitId) { + return {name: 'nonprofit-donations-list', params: {nonprofitId: this.nonprofitId}}; } return {name: 'donations-list'}; } }, props: [ - 'nonprofitUuid' + 'nonprofitId' ], created: function () { const vue = this; diff --git a/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue b/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue index 38e1280a..df28c772 100644 --- a/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue +++ b/packages/frontend/src/admin-pages/components/header/NavigationNonprofits.vue @@ -18,13 +18,13 @@
@@ -50,7 +50,7 @@ this.setSelected(); }, props: [ - 'nonprofitUuid' + 'nonprofitId' ], methods: { setSelected: function () { diff --git a/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue b/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue index 3a9ab559..aaea1538 100644 --- a/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue +++ b/packages/frontend/src/admin-pages/components/nonprofit/donations/DonationsList.vue @@ -16,7 +16,7 @@