cloudformation/tag-manager.yaml (464 lines of code) (raw):
AWSTemplateFormatVersion: '2010-09-09'
Description: tag-manager
Parameters:
Stage:
Description: Environment name
Type: String
AllowedValues:
- PROD
- CODE
Default: PROD
VpcId:
Description: ID of the VPC onto which to launch the application eg. vpc-1234abcd
Type: AWS::EC2::VPC::Id
Default: vpc-381fa95d
PublicVpcSubnets:
Description: Subnets to use in VPC for public internet-facing ELB eg. subnet-abcd1234
Type: List<AWS::EC2::Subnet::Id>
Default: subnet-c3620fa6,subnet-2b37bd5c,subnet-3667c86f
PrivateVpcSubnets:
Description: Subnets to use in VPC for private EC2 instances eg. subnet-abcd1234
Type: List<AWS::EC2::Subnet::Id>
Default: subnet-c2620fa7,subnet-2a37bd5d,subnet-2967c870
AMI:
Description: AMI id
Type: String
GuardianIP:
Description: Ip range for the office
Type: String
Default: 77.91.248.0/21
CertificateArn:
Description: ARN of the SSL certificate for this service
Type: String
VulnerabilityScanningSecurityGroup:
Description: Security group that grants access to the account's Vulnerability
Scanner
Type: AWS::EC2::SecurityGroup::Id
CapiPreviewRole:
Type: String
Description: ARN of the CAPI preview role
AlertTopicArn:
Description: The ARN of the SNS topic to notify when an alarm occurs
Type: AWS::SSM::Parameter::Value<String>
Default: /account/services/alert.topic.arn
LoggingStreamName:
Type: AWS::SSM::Parameter::Value<String>
Description: Name of the kinesis stream for logging to ELK (logs.gutools)
Default: /account/services/logging.stream.name
LoggingStreamArn:
Type: AWS::SSM::Parameter::Value<String>
Description: ARN of the kinesis stream for logging to ELK (logs.gutools)
Default: /account/services/logging.stream
Conditions:
IsProd: !Equals [!Ref Stage, PROD]
Mappings:
Config:
CODE:
MinSize: 1
MaxSize: 2
DesiredCapacity: 1
InstanceType: t4g.medium
DNSName: tagmanager.code.dev-gutools.co.uk
PROD:
MinSize: 3
MaxSize: 6
DesiredCapacity: 3
InstanceType: t4g.medium
DNSName: tagmanager.gutools.co.uk
Resources:
TagManagerRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- Fn::ImportValue: !Sub "guardian-ec2-for-ssm-GuardianEC2ForSSMPolicy"
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
TagManagerDescribeEC2Policy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagersDescribeEC2Policy
PolicyDocument:
Statement:
- Effect: Allow
Resource: "*"
Action:
- ec2:Describe*
- autoscaling:DescribeAutoScalingGroups
- autoscaling:DescribeAutoScalingInstances
Roles:
- !Ref 'TagManagerRole'
TagManagerGetDistributablesPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerGetDistributablesPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource:
- arn:aws:s3:::composer-dist/*
Roles:
- !Ref 'TagManagerRole'
TagManagerGetConfigPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerGetConfigPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource:
- arn:aws:s3:::guconf-flexible/tag-manager/*
Roles:
- !Ref 'TagManagerRole'
TagManagerPanDomainPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerPanDomainPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource:
- arn:aws:s3:::pan-domain-auth-settings/*
Roles:
- !Ref 'TagManagerRole'
TagManagerStaticFilesWritePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerStaticFilesWritePolicy
PolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRole
Resource: arn:aws:iam::642631414762:role/composerWriteToStaticBucket
Roles:
- !Ref 'TagManagerRole'
TagManagerPermissionsBucketPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerPermissionsBucketPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource:
- arn:aws:s3:::permissions-cache/*
Roles:
- !Ref 'TagManagerRole'
TagManagerCloudwatchPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerCloudwatchPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- cloudwatch:*
Resource: '*'
Roles:
- !Ref 'TagManagerRole'
TagManagersDynamoPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerDynamoPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- dynamodb:*
Resource: '*'
Roles:
- !Ref 'TagManagerRole'
TagManagerKinesisPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerKinesisPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- kinesis:*
Resource: '*'
Roles:
- !Ref 'TagManagerRole'
TagManagerSQSPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: TagManagerSQSPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- sqs:*
Resource: '*'
Roles:
- !Ref 'TagManagerRole'
LogServerPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: LogServerPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- kinesis:PutRecord
- kinesis:PutRecords
- kinesis:DescribeStream
Resource: !Ref LoggingStreamArn
Roles:
- !Ref 'TagManagerRole'
TagManagerInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref 'TagManagerRole'
AppServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: tag manager Application servers
VpcId: !Ref 'VpcId'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 9000
ToPort: 9000
CidrIp: !Ref 'GuardianIP'
- IpProtocol: tcp
FromPort: 9000
ToPort: 9000
SourceSecurityGroupId: !Ref 'LoadBalancerSecurityGroup'
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: tag manager application load balancer
VpcId: !Ref 'VpcId'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '443'
ToPort: '443'
CidrIp: 0.0.0.0/0
TagManagerLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
SecurityGroups:
- !GetAtt [LoadBalancerSecurityGroup, GroupId]
CrossZone: true
Subnets: !Ref 'PublicVpcSubnets'
Listeners:
- LoadBalancerPort: '80'
InstancePort: '9000'
Protocol: HTTP
- LoadBalancerPort: '443'
InstancePort: '9000'
Protocol: HTTPS
SSLCertificateId: !Ref 'CertificateArn'
HealthCheck:
Target: HTTP:9000/management/healthcheck
HealthyThreshold: '2'
UnhealthyThreshold: '2'
Interval: '10'
Timeout: '5'
Tags:
- Key: Stage
Value: !Ref 'Stage'
- Key: Stack
Value: flexible
- Key: App
Value: tag-manager
TagManagerCloudfrontCachePolicy:
Type: "AWS::CloudFront::CachePolicy"
Properties:
CachePolicyConfig:
DefaultTTL: 0
MaxTTL: 3600
MinTTL: 0
Name: !Sub "tag-manager-cache-policy-${Stage}"
ParametersInCacheKeyAndForwardedToOrigin:
CookiesConfig:
CookieBehavior: "all"
EnableAcceptEncodingBrotli: true
EnableAcceptEncodingGzip: true
HeadersConfig:
HeaderBehavior: "whitelist"
Headers:
- "Host"
- "Origin"
- "Access-Control-Request-Headers"
- "Access-Control-Request-Method"
- "X-Gu-Tools-HMAC-Token"
- "X-Gu-Tools-HMAC-Date"
- "X-Gu-Tools-Service-Name"
QueryStringsConfig:
QueryStringBehavior: "all"
TagManagerCloudFrontDistribution:
Type: "AWS::CloudFront::Distribution"
Properties:
DistributionConfig:
Aliases:
- !FindInMap [Config, !Ref 'Stage', DNSName]
DefaultCacheBehavior:
AllowedMethods:
- "GET"
- "HEAD"
- "OPTIONS"
- "PUT"
- "PATCH"
- "POST"
- "DELETE"
CachePolicyId: !Ref 'TagManagerCloudfrontCachePolicy'
Compress: true
TargetOriginId: !Ref 'TagManagerLoadBalancer'
ViewerProtocolPolicy: "redirect-to-https"
Enabled: true
HttpVersion: "http2"
IPV6Enabled: true
Origins:
- CustomOriginConfig:
OriginProtocolPolicy: "https-only"
OriginSSLProtocols:
- "TLSv1.2"
DomainName: !GetAtt TagManagerLoadBalancer.DNSName
Id: !Ref 'TagManagerLoadBalancer'
ViewerCertificate:
AcmCertificateArn: !Sub '{{resolve:ssm:/${Stage}/flexible/tagmanager/cloudFrontCertificateArn}}'
MinimumProtocolVersion: "TLSv1.2_2021"
SslSupportMethod: "sni-only"
Tags:
- Key: "gu:repo"
Value: "guardian/tagmanager"
- Key: Stack
Value: flexible
- Key: Stage
Value: !Ref 'Stage'
- Key: App
Value: tag-manager
AutoscalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones: !GetAZs ''
VPCZoneIdentifier: !Ref 'PrivateVpcSubnets'
LaunchConfigurationName: !Ref 'TagManagerLaunchConfig'
MinSize: !FindInMap [Config, !Ref 'Stage', MinSize]
MaxSize: !FindInMap [Config, !Ref 'Stage', MaxSize]
DesiredCapacity: !FindInMap [Config, !Ref 'Stage', DesiredCapacity]
HealthCheckType: ELB
HealthCheckGracePeriod: 300
LoadBalancerNames:
- !Ref 'TagManagerLoadBalancer'
Tags:
- Key: Stage
Value: !Ref 'Stage'
PropagateAtLaunch: 'true'
- Key: Stack
Value: flexible
PropagateAtLaunch: 'true'
- Key: App
Value: tag-manager
PropagateAtLaunch: 'true'
- Key: LogKinesisStreamName
Value: !Ref 'LoggingStreamName'
PropagateAtLaunch: 'true'
- Key: SystemdUnit
Value: tag-manager.service
PropagateAtLaunch: 'true'
TagManagerDNSRecord:
Type: Guardian::DNS::RecordSet
Properties:
Name: !FindInMap [Config, !Ref 'Stage', DNSName]
RecordType: CNAME
ResourceRecords:
- Fn::Join:
- ""
- - !GetAtt TagManagerCloudFrontDistribution.DomainName
- "."
Stage: !Ref Stage
TTL: 3600
TagManagerLaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !Ref 'AMI'
SecurityGroups:
- !Ref 'AppServerSecurityGroup'
- !Ref 'VulnerabilityScanningSecurityGroup'
InstanceType: !FindInMap [Config, !Ref 'Stage', InstanceType]
IamInstanceProfile: !Ref 'TagManagerInstanceProfile'
MetadataOptions:
HttpTokens: required
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -ev
aws s3 cp s3://composer-dist/flexible/${Stage}/tag-manager/tag-manager.deb /tmp
dpkg -i /tmp/tag-manager.deb
AssumeCapiPreviewRolePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: assume-capi-preview-role
PolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRole
Resource:
Ref: CapiPreviewRole
Roles:
- Ref: TagManagerRole
Tagmanager5XXAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
TreatMissingData: notBreaching
AlarmDescription: Tag manager is returning 5x responses
ComparisonOperator: GreaterThanOrEqualToThreshold
Threshold: '10'
EvaluationPeriods: '3'
Metrics:
- Expression: backend5XX + elb5XX
Id: sum
Label: "Count of Backend AND ELB 5XX"
ReturnData: true
- Id: backend5XX
ReturnData: false
Label: "backend5XX"
MetricStat:
Metric:
MetricName: HTTPCode_Backend_5XX
Namespace: AWS/ELB
Dimensions:
- Name: LoadBalancerName
Value: !Ref 'TagManagerLoadBalancer'
Period: 300
Stat: Sum
Unit: Count
- Id: elb5XX
ReturnData: false
Label: "elb5XX"
MetricStat:
Metric:
MetricName: HTTPCode_ELB_5XX
Namespace: AWS/ELB
Dimensions:
- Name: LoadBalancerName
Value: !Ref 'TagManagerLoadBalancer'
Period: 300
Stat: Sum
Unit: Count
AlarmActions:
- !Ref 'AlertTopicArn'
OKActions:
- !Ref 'AlertTopicArn'