report/conf/report.yaml (300 lines of code) (raw):

AWSTemplateFormatVersion: '2010-09-09' Description: Reporting for mobile notifications Mappings: Constants: App: Value: report Stack: Value: mobile-notifications StageVariables: CODE: NotificationAlarmPeriod: 1200 ScalingUpPeriod: 300 ScalingUpThreshold: 20 ScalingDownPeriod: 300 ScalingDownThreshold: 15 InstanceType: "t4g.micro" PROD: NotificationAlarmPeriod: 1200 ScalingUpPeriod: 300 ScalingUpThreshold: 20 ScalingDownPeriod: 300 ScalingDownThreshold: 15 InstanceType: "t4g.micro" Outputs: LoadBalancerUrl: Value: !GetAtt LoadBalancerToPrivateASG.DNSName Parameters: AMI: Description: AMI used by the instances, Type: AWS::EC2::Image::Id Stage: Type: String AllowedValues: - CODE - PROD Description: Environment name VPCSecurityGroup: Type: AWS::EC2::SecurityGroup::Id Description: The default security group of the VPC VpcId: Type: AWS::EC2::VPC::Id Description: The VPC PublicSubnets: Type: List<AWS::EC2::Subnet::Id> Description: The public subnets of the VPC for the loadbalancer PrivateSubnets: Type: List<AWS::EC2::Subnet::Id> Description: The private subnets of the VPC for the autoscaling group ASGMinSize: Type: Number Description: Minimum size of the autoscaling group ASGMaxSize: Type: Number Description: Maximum size of the autoscaling group DistBucket: Type: String Description: The name of the s3 bucket containing the server artifact AppCertArn: Type: String Description: ACM Certificate for app use HostedZone: Type: String Description: The HostedZone, should contain the trailing dot zone.example.com. DomainName: Type: String Description: The domain name of the ELB, should contain the trailing dot stuff.zone.example.com. Resources: DnsRecord: Type: AWS::Route53::RecordSet Properties: HostedZoneName: !Ref HostedZone Name: !Ref DomainName ResourceRecords: - !GetAtt LoadBalancerToPrivateASG.DNSName TTL: 60 Type: CNAME GuardianAccessSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: SSH and management server access from Guardian network SecurityGroupIngress: - SourceSecurityGroupId: !Ref VPCSecurityGroup FromPort: 22 IpProtocol: tcp ToPort: 22 VpcId: !Ref VpcId HighCpuAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: [!Ref ScaleUpPolicy] AlarmDescription: !Sub - Scale-Up if cpu is greater than ${Threshold}% over last ${Period} seconds - Threshold: !FindInMap [ StageVariables, !Ref Stage, ScalingUpThreshold ] Period: !FindInMap [ StageVariables, !Ref Stage, ScalingUpPeriod ] ComparisonOperator: GreaterThanOrEqualToThreshold Dimensions: - Name: AutoScalingGroupName Value: !Ref PrivateReportAutoscalingGroup EvaluationPeriods: 1 MetricName: CPUUtilization Namespace: AWS/EC2 Period: !FindInMap [ StageVariables, !Ref Stage, ScalingUpPeriod ] Statistic: Average Threshold: !FindInMap [ StageVariables, !Ref Stage, ScalingUpThreshold ] LowCpuAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: [!Ref ScaleDownPolicy] AlarmDescription: !Sub - Scale-Down if cpu is lower than ${Threshold}% over last ${Period} seconds - Threshold: !FindInMap [ StageVariables, !Ref Stage, ScalingDownThreshold ] Period: !FindInMap [ StageVariables, !Ref Stage, ScalingDownPeriod ] ComparisonOperator: LessThanThreshold Dimensions: - Name: AutoScalingGroupName Value: !Ref PrivateReportAutoscalingGroup EvaluationPeriods: 1 MetricName: CPUUtilization Namespace: AWS/EC2 Period: !FindInMap [ StageVariables, !Ref Stage, ScalingDownPeriod ] Statistic: Average Threshold: !FindInMap [ StageVariables, !Ref Stage, ScalingDownThreshold ] InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Open up HTTP access to load balancer SecurityGroupEgress: - CidrIp: 0.0.0.0/0 FromPort: 80 IpProtocol: tcp ToPort: 80 - CidrIp: 0.0.0.0/0 FromPort: 443 IpProtocol: tcp ToPort: 443 SecurityGroupIngress: - FromPort: 9000 IpProtocol: tcp SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup ToPort: 9000 VpcId: !Ref VpcId LoadBalancerToPrivateASG: Type: AWS::ElasticLoadBalancing::LoadBalancer Properties: CrossZone: true HealthCheck: HealthyThreshold: 2 Interval: 30 Target: HTTP:9000/healthcheck Timeout: 10 UnhealthyThreshold: 10 Listeners: - InstancePort: 9000 LoadBalancerPort: 443 Protocol: HTTPS SSLCertificateId: !Ref AppCertArn SecurityGroups: - !Ref LoadBalancerSecurityGroup Subnets: !Ref PublicSubnets LoadBalancerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Open up HTTP access to load balancer SecurityGroupEgress: - CidrIp: 0.0.0.0/0 FromPort: 9000 IpProtocol: tcp ToPort: 9000 SecurityGroupIngress: - CidrIp: 0.0.0.0/0 FromPort: 443 IpProtocol: tcp ToPort: 443 VpcId: !Ref VpcId NotificationsReportInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref NotificationsReportRole NotificationsReportRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - ec2.amazonaws.com Path: / ManagedPolicyArns: [ !Sub 'arn:aws:iam::${AWS::AccountId}:policy/ssm-scala-v1' ] Policies: - PolicyName: root PolicyDocument: Statement: - Action: s3:GetObject Effect: Allow Resource: !Sub arn:aws:s3:::${DistBucket}/* - Action: ec2:DescribeTags Effect: Allow Resource: '*' - Action: - cloudwatch:* - logs:* Effect: Allow Resource: '*' - Action: - autoscaling:DescribeAutoScalingInstances - autoscaling:DescribeAutoScalingGroups Resource: '*' Effect: Allow - Effect: Allow Action: - kinesis:PutRecord - kinesis:PutRecords - kinesis:DescribeStream Resource: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/mobile-log-aggregation-${Stage} - PolicyName: dynamo PolicyDocument: Statement: - Action: dynamodb:* Effect: Allow Resource: - !Sub arn:aws:dynamodb:eu-west-1:${AWS::AccountId}:table/mobile-notifications-reports-${Stage} - !Sub arn:aws:dynamodb:eu-west-1:${AWS::AccountId}:table/mobile-notifications-reports-${Stage}/index/* - PolicyName: conf PolicyDocument: Statement: - Action: ssm:GetParametersByPath Effect: Allow Resource: !Sub - arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/notifications/${Stage}/${Stack} - Stack: !FindInMap [Constants, Stack, Value] PrivateReportAutoscalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AvailabilityZones: !GetAZs HealthCheckGracePeriod: 400 HealthCheckType: ELB LaunchConfigurationName: !Ref ReportLaunchConfig LoadBalancerNames: - !Ref LoadBalancerToPrivateASG MaxSize: !Ref ASGMaxSize MinSize: !Ref ASGMinSize NotificationConfiguration: NotificationTypes: - autoscaling:EC2_INSTANCE_LAUNCH_ERROR - autoscaling:EC2_INSTANCE_TERMINATE_ERROR TopicARN: !Sub arn:aws:sns:eu-west-1:${AWS::AccountId}:AutoscalingNotifications${Stage} Tags: - Key: Stage PropagateAtLaunch: true Value: !Ref Stage - Key: Stack PropagateAtLaunch: true Value: !FindInMap [Constants, Stack, Value] - Key: App PropagateAtLaunch: true Value: !FindInMap [Constants, App, Value] VPCZoneIdentifier: !Ref PrivateSubnets ReportLaunchConfig: Type: AWS::AutoScaling::LaunchConfiguration Properties: AssociatePublicIpAddress: false IamInstanceProfile: !Ref NotificationsReportInstanceProfile ImageId: !Ref AMI InstanceType: !FindInMap [StageVariables, !Ref Stage, InstanceType] SecurityGroups: - !Ref InstanceSecurityGroup - !Ref GuardianAccessSecurityGroup - !Ref VPCSecurityGroup MetadataOptions: HttpTokens: required UserData: Fn::Base64: !Sub - | #!/bin/bash -ev aws --region ${AWS::Region} s3 cp s3://${DistBucket}/${Stack}/${Stage}/${App}/${App}_1.0-latest_all.deb /tmp dpkg -i /tmp/${App}_1.0-latest_all.deb /opt/aws-kinesis-agent/configure-aws-kinesis-agent ${AWS::Region} mobile-log-aggregation-${Stage} /var/log/${App}/application.log - Stack: !FindInMap [Constants, Stack, Value] App: !FindInMap [Constants, App, Value] ScaleDownPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: AdjustmentType: ChangeInCapacity AutoScalingGroupName: !Ref PrivateReportAutoscalingGroup Cooldown: 3600 ScalingAdjustment: -1 ScaleUpPolicy: Type: AWS::AutoScaling::ScalingPolicy Properties: AdjustmentType: PercentChangeInCapacity AutoScalingGroupName: !Ref PrivateReportAutoscalingGroup Cooldown: 300 ScalingAdjustment: 100