Created
April 28, 2020 16:52
-
-
Save nkhine/9b16c6929ab6d05ae816495d187ef697 to your computer and use it in GitHub Desktop.
HA Crucible
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
AWSTemplateFormatVersion: '2010-09-09' | |
Description: 'Crucible: highly available Fisheye/Crucible template.' | |
Metadata: | |
'AWS::CloudFormation::Interface': | |
ParameterGroups: | |
- Label: | |
default: 'Parent Stacks' | |
Parameters: | |
- ParentVPCStack | |
- ParentSSHBastionStack | |
- ParentAuthProxyStack | |
- ParentAlertStack | |
- ParentS3StackAccessLog | |
- ParentZoneStack | |
- Label: | |
default: 'EC2 Parameters' | |
Parameters: | |
- KeyName | |
- IAMUserSSHAccess | |
- SystemsManagerAccess | |
- SubDomainNameWithDot | |
- ManagedPolicyArns | |
- Label: | |
default: 'EFS Parameters' | |
Parameters: | |
- EFSProvisionedThroughputInMibps | |
- EFSBackupRetentionPeriod | |
- EFSBackupScheduleExpression | |
- Label: | |
default: 'Master Parameters' | |
Parameters: | |
- MasterSubnetsReach | |
- MasterELBScheme | |
- MasterInstanceType | |
- MasterLogsRetentionInDays | |
- MasterVolumeSize | |
- MasterLoadBalancerIdleTimeout | |
Parameters: | |
ParentVPCStack: | |
Description: 'Stack name of parent VPC stack based on vpc/vpc-*azs.yaml template.' | |
Type: String | |
ParentSSHBastionStack: | |
Description: 'Optional but recommended stack name of parent SSH bastion host/instance stack based on vpc/vpc-*-bastion.yaml template.' | |
Type: String | |
Default: '' | |
ParentAuthProxyStack: | |
Description: 'Optional stack name of parent auth proxy stack based on security/auth-proxy-*.yaml template.' | |
Type: String | |
Default: '' | |
ParentAlertStack: | |
Description: 'Optional but recommended stack name of parent alert stack based on operations/alert.yaml template.' | |
Type: String | |
Default: '' | |
ParentS3StackAccessLog: | |
Description: 'Optional stack name of parent s3 stack based on state/s3.yaml template (with Access set to ElbAccessLogWrite) to store access logs.' | |
Type: String | |
Default: '' | |
ParentZoneStack: | |
Description: 'Optional stack name of parent zone stack based on vpc/zone-*.yaml template.' | |
Type: String | |
Default: '' | |
KeyName: | |
Description: 'Optional key pair of the ec2-user to establish a SSH connection to the Jenkins master and agents.' | |
Type: String | |
Default: '' | |
IAMUserSSHAccess: | |
Description: 'Synchronize public keys of IAM users to enable personalized SSH access (Doc: https://cloudonaut.io/manage-aws-ec2-ssh-access-with-iam/).' | |
Type: String | |
Default: false | |
AllowedValues: | |
- true | |
- false | |
SystemsManagerAccess: | |
Description: 'Enable AWS Systems Manager agent and authorization.' | |
Type: String | |
Default: true | |
AllowedValues: | |
- true | |
- false | |
MasterSubnetsReach: | |
Description: 'Should the master have direct access to the Internet or do you prefer private subnets with NAT?' | |
Type: String | |
Default: Public | |
AllowedValues: | |
- Public | |
- Private | |
MasterELBScheme: | |
Description: 'Indicates whether the load balancer in front of the Jenkins master is Internet-facing or internal.' | |
Type: String | |
Default: 'internet-facing' | |
AllowedValues: | |
- 'internet-facing' | |
- internal | |
MasterInstanceType: | |
Description: 'The instance type of the Jenkins master.' | |
Type: String | |
Default: 't2.micro' | |
MasterLogsRetentionInDays: | |
Description: 'Specifies the number of days you want to retain log events in the specified log group.' | |
Type: Number | |
Default: 14 | |
AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] | |
MasterVolumeSize: | |
Description: 'The root volume size, in Gibibytes (GiB). Keep in mind that Jenkins home lives on EFS.' | |
Type: Number | |
Default: 8 | |
ConstraintDescription: 'Must be in the range [8-1024]' | |
MinValue: 8 | |
MaxValue: 1024 | |
MasterLoadBalancerIdleTimeout: | |
Description: 'The idle timeout value, in seconds.' | |
Type: Number | |
Default: 60 | |
MinValue: 1 | |
MaxValue: 4000 | |
MasterEnableMetrics: | |
Description: 'Should the master have Group Metrics collection enabled?' | |
Type: String | |
Default: "true" | |
AllowedValues: ["true", "false"] | |
SubDomainNameWithDot: | |
Description: 'Name that is used to create the DNS entry with trailing dot, e.g. §{SubDomainNameWithDot}§{HostedZoneName}. Leave blank for naked (or apex and bare) domain. Requires ParentZoneStack parameter!' | |
Type: String | |
Default: 'crucible.' | |
ManagedPolicyArns: | |
Description: 'Optional comma-delimited list of IAM managed policy ARNs to attach to the instance''s IAM role' | |
Type: String | |
Default: '' | |
EFSProvisionedThroughputInMibps: | |
Description: 'The provisioned throughput for the Elastic File System (EFS) in Mibps. Default is 0 which enables the bursting mode and disables provisioned throughput.' | |
Type: Number | |
Default: 0 | |
EFSBackupRetentionPeriod: | |
Description: 'The number of days to keep backups of the EFS file system (set to 0 to disable).' | |
Type: Number | |
MinValue: 0 | |
MaxValue: 35 | |
Default: 30 | |
EFSBackupScheduleExpression: | |
Description: 'A CRON expression specifying when AWS Backup initiates a backup job.' | |
Type: String | |
Default: 'cron(0 5 ? * * *)' | |
CertificateArn: | |
Description: 'SSL certificate arn' | |
Type: String | |
Mappings: | |
RegionMap: | |
'eu-north-1': | |
AMI: 'ami-0b7a46b4bd694e8a6' | |
'ap-south-1': | |
AMI: 'ami-0470e33cd681b2476' | |
'eu-west-3': | |
AMI: 'ami-00077e3fed5089981' | |
'eu-west-2': | |
AMI: 'ami-01a6e31ac994bbc09' | |
'eu-west-1': | |
AMI: 'ami-06ce3edf0cff21f07' | |
'ap-northeast-2': | |
AMI: 'ami-01288945bd24ed49a' | |
'me-south-1': | |
AMI: 'ami-0fde637e0db57a2ab' | |
'ap-northeast-1': | |
AMI: 'ami-0f310fced6141e627' | |
'sa-east-1': | |
AMI: 'ami-003449ffb2605a74c' | |
'ca-central-1': | |
AMI: 'ami-054362537f5132ce2' | |
'ap-east-1': | |
AMI: 'ami-dd7731ac' | |
'ap-southeast-1': | |
AMI: 'ami-0ec225b5e01ccb706' | |
'ap-southeast-2': | |
AMI: 'ami-0970010f37c4f9c8d' | |
'eu-central-1': | |
AMI: 'ami-076431be05aaf8080' | |
'us-east-1': | |
AMI: 'ami-0323c3dd2da7fb37d' | |
'us-east-2': | |
AMI: 'ami-0f7919c33c90f5b58' | |
'us-west-1': | |
AMI: 'ami-06fcc1f0bc2c8943f' | |
'us-west-2': | |
AMI: 'ami-0d6621c01e8c2de2c' | |
AWSRegionsNameMapping: | |
eu-west-1: | |
RegionName: Ireland | |
eu-west-2: | |
RegionName: London | |
SSLmapping: | |
ssl1: | |
London: 'arn:aws:acm:eu-west-2:xxxxxxxxx:certificate/xxxxxxxxxxxxx' | |
Ireland: 'arn:aws:acm:eu-west-1:xxxxxxxxx:certificate/xxxxxxxxxxxxx' | |
Conditions: | |
HasKeyName: !Not [!Equals [!Ref KeyName, '']] | |
HasIAMUserSSHAccess: !Equals [!Ref IAMUserSSHAccess, 'true'] | |
HasSystemsManagerAccess: !Equals [!Ref SystemsManagerAccess, 'true'] | |
HasSSHBastionSecurityGroup: !Not [!Equals [!Ref ParentSSHBastionStack, '']] | |
HasNotSSHBastionSecurityGroup: !Equals [!Ref ParentSSHBastionStack, ''] | |
HasAuthProxySecurityGroup: !Not [!Equals [!Ref ParentAuthProxyStack, '']] | |
HasNotAuthProxySecurityGroup: !Equals [!Ref ParentAuthProxyStack, ''] | |
HasMasterELBSchemeInternal: !Equals [!Ref MasterELBScheme, 'internal'] | |
HasAlertTopic: !Not [!Equals [!Ref ParentAlertStack, '']] | |
HasS3Bucket: !Not [!Equals [!Ref ParentS3StackAccessLog, '']] | |
HasZone: !Not [!Equals [!Ref ParentZoneStack, '']] | |
HasManagedPolicyArns: !Not [!Equals [!Ref ManagedPolicyArns, '']] | |
HasEFSProvisionedThroughput: !Not [!Condition HasNotEFSProvisionedThroughput] | |
HasNotEFSProvisionedThroughput: !Equals [!Ref EFSProvisionedThroughputInMibps, '0'] | |
HasAlertTopicAndEFSProvisionedThroughput: !And [!Condition HasAlertTopic, !Condition HasEFSProvisionedThroughput] | |
HasAlertTopicAndNotEFSProvisionedThroughput: !And [!Condition HasAlertTopic, !Condition HasNotEFSProvisionedThroughput] | |
HasEFSBackupRetentionPeriod: !Not [!Equals [!Ref EFSBackupRetentionPeriod, 0]] | |
HasMasterMetrics: !Equals [!Ref MasterEnableMetrics, "true"] | |
Resources: | |
MasterStorageSG: | |
Type: 'AWS::EC2::SecurityGroup' | |
Properties: | |
GroupDescription: 'crucible-master' | |
VpcId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC'} | |
SecurityGroupIngress: | |
- SourceSecurityGroupId: !Ref MasterSG | |
FromPort: 2049 | |
ToPort: 2049 | |
IpProtocol: tcp | |
MasterStorage: | |
Type: 'AWS::EFS::FileSystem' | |
Properties: | |
ThroughputMode: !If [HasEFSProvisionedThroughput, 'provisioned', 'bursting'] | |
ProvisionedThroughputInMibps: !If [HasEFSProvisionedThroughput, !Ref EFSProvisionedThroughputInMibps, !Ref 'AWS::NoValue'] | |
FileSystemTags: | |
- Key: Name | |
Value: 'crucible-master-storage' | |
PerformanceMode: generalPurpose | |
MasterStorageBurstCreditBalanceTooLowAlarm: | |
Condition: HasAlertTopicAndNotEFSProvisionedThroughput | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Average burst credit balance over last 10 minutes too low, expect a significant performance drop soon.' | |
Namespace: 'AWS/EFS' | |
MetricName: BurstCreditBalance | |
Statistic: Average | |
Period: 600 | |
EvaluationPeriods: 1 | |
ComparisonOperator: LessThanThreshold | |
Threshold: 192000000000 # 192 GB in Bytes (last hour where you can burst at 100 MB/sec) | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: FileSystemId | |
Value: !Ref MasterStorage | |
MasterStoragePercentIOLimitTooHighAlarm: | |
Condition: HasAlertTopicAndNotEFSProvisionedThroughput | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'I/O limit has been reached, consider using Max I/O performance mode.' | |
Namespace: 'AWS/EFS' | |
MetricName: PercentIOLimit | |
Statistic: Maximum | |
Period: 600 | |
EvaluationPeriods: 3 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: 95 | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: FileSystemId | |
Value: !Ref MasterStorage | |
MasterStorageThroughputAlarm: | |
Condition: HasAlertTopicAndEFSProvisionedThroughput | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Reached 90% of the provisioned throughput over last 10 minutes.' | |
Namespace: 'AWS/EFS' | |
MetricName: TotalIOBytes | |
Statistic: Sum | |
Period: 600 | |
EvaluationPeriods: 1 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: !GetAtt MaxThroughputCalculator.Threshold | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: FileSystemId | |
Value: !Ref MasterStorage | |
MasterStorageMountTargetA: | |
Type: 'AWS::EFS::MountTarget' | |
Properties: | |
FileSystemId: !Ref MasterStorage | |
SecurityGroups: | |
- !Ref MasterStorageSG | |
SubnetId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetA${MasterSubnetsReach}'} | |
MasterStorageMountTargetB: | |
Type: 'AWS::EFS::MountTarget' | |
Properties: | |
FileSystemId: !Ref MasterStorage | |
SecurityGroups: | |
- !Ref MasterStorageSG | |
SubnetId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetB${MasterSubnetsReach}'} | |
MasterELBSG: | |
Type: 'AWS::EC2::SecurityGroup' | |
Properties: | |
GroupDescription: 'crucible-elb-master' | |
VpcId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC'} | |
# Was missing | |
MasterELBSGInWorld: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Condition: HasNotAuthProxySecurityGroup | |
Properties: | |
GroupId: !Ref MasterELBSG | |
IpProtocol: tcp | |
FromPort: 80 | |
ToPort: 80 | |
CidrIp: '0.0.0.0/0' | |
MasterELBSGInAuthProxy: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Condition: HasAuthProxySecurityGroup | |
Properties: | |
GroupId: !Ref MasterELBSG | |
IpProtocol: tcp | |
FromPort: 80 | |
ToPort: 80 | |
SourceSecurityGroupId: {'Fn::ImportValue': !Sub '${ParentAuthProxyStack}-SecurityGroup'} | |
MasterELBHTTPSSGInAuthProxy: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Condition: HasAuthProxySecurityGroup | |
Properties: | |
GroupId: !Ref MasterELBSG | |
IpProtocol: tcp | |
FromPort: 443 | |
ToPort: 443 | |
SourceSecurityGroupId: {'Fn::ImportValue': !Sub '${ParentAuthProxyStack}-SecurityGroup'} | |
MasterHTTPCodeELB5XXTooHighAlarm: | |
Condition: HasAlertTopic | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Application load balancer returns 5XX HTTP status codes' | |
Namespace: 'AWS/ApplicationELB' | |
MetricName: HTTPCode_ELB_5XX_Count | |
Statistic: Sum | |
Period: 60 | |
EvaluationPeriods: 1 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: 0 | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: LoadBalancer | |
Value: !GetAtt MasterELB.LoadBalancerFullName | |
TreatMissingData: notBreaching | |
MasterHTTPCodeTarget5XXTooHighAlarm: | |
Condition: HasAlertTopic | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Application load balancer receives 5XX HTTP status codes from targets' | |
Namespace: 'AWS/ApplicationELB' | |
MetricName: HTTPCode_Target_5XX_Count | |
Statistic: Sum | |
Period: 60 | |
EvaluationPeriods: 1 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: 0 | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: LoadBalancer | |
Value: !GetAtt MasterELB.LoadBalancerFullName | |
TreatMissingData: notBreaching | |
MasterRejectedConnectionCountTooHighAlarm: | |
Condition: HasAlertTopic | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Application load balancer rejected connections because the load balancer had reached its maximum number of connections' | |
Namespace: 'AWS/ApplicationELB' | |
MetricName: RejectedConnectionCount | |
Statistic: Sum | |
Period: 60 | |
EvaluationPeriods: 1 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: 0 | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: LoadBalancer | |
Value: !GetAtt MasterELB.LoadBalancerFullName | |
TreatMissingData: notBreaching | |
MasterTargetConnectionErrorCountTooHighAlarm: | |
Condition: HasAlertTopic | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Application load balancer could not connect to targets' | |
Namespace: 'AWS/ApplicationELB' | |
MetricName: TargetConnectionErrorCount | |
Statistic: Sum | |
Period: 60 | |
EvaluationPeriods: 1 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: 0 | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: LoadBalancer | |
Value: !GetAtt MasterELB.LoadBalancerFullName | |
TreatMissingData: notBreaching | |
RecordSet: | |
Condition: HasZone | |
Type: 'AWS::Route53::RecordSet' | |
Properties: | |
AliasTarget: | |
HostedZoneId: !GetAtt 'MasterELB.CanonicalHostedZoneID' | |
DNSName: !GetAtt 'MasterELB.DNSName' | |
HostedZoneId: {'Fn::ImportValue': !Sub '${ParentZoneStack}-HostedZoneId'} | |
Name: !Sub | |
- '${SubDomainNameWithDot}${HostedZoneName}' | |
- SubDomainNameWithDot: !Ref SubDomainNameWithDot | |
HostedZoneName: {'Fn::ImportValue': !Sub '${ParentZoneStack}-HostedZoneName'} | |
Type: A | |
MasterELB: | |
Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' | |
Properties: | |
LoadBalancerAttributes: | |
- Key: 'idle_timeout.timeout_seconds' | |
Value: !Ref MasterLoadBalancerIdleTimeout | |
- Key: 'routing.http2.enabled' | |
Value: 'true' | |
- Key: 'access_logs.s3.enabled' | |
Value: !If [HasS3Bucket, 'true', 'false'] | |
- !If [HasS3Bucket, {Key: 'access_logs.s3.prefix', Value: !Ref 'AWS::StackName'}, !Ref 'AWS::NoValue'] | |
- !If [HasS3Bucket, {Key: 'access_logs.s3.bucket', Value: {'Fn::ImportValue': !Sub '${ParentS3StackAccessLog}-BucketName'}}, !Ref 'AWS::NoValue'] | |
Scheme: !Ref MasterELBScheme | |
SecurityGroups: | |
- !Ref MasterELBSG | |
Subnets: !If | |
- HasMasterELBSchemeInternal | |
- - {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetAPrivate'} | |
- {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetBPrivate'} | |
- - {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetAPublic'} | |
- {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetBPublic'} | |
Tags: | |
- Key: Name | |
Value: 'crucible-master' | |
MasterELBTargetGroup: # not monitored, but MasterELB is monitored! | |
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' | |
Properties: | |
HealthCheckIntervalSeconds: 30 | |
HealthCheckPath: '/login' | |
HealthCheckPort: '8060' | |
HealthCheckProtocol: HTTP | |
HealthCheckTimeoutSeconds: 25 | |
HealthyThresholdCount: 2 | |
UnhealthyThresholdCount: 2 | |
Matcher: | |
HttpCode: '200-302' | |
Port: 8060 | |
Protocol: HTTP | |
Tags: | |
- Key: Name | |
Value: 'crucible-master' | |
VpcId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC'} | |
TargetGroupAttributes: | |
- Key: 'deregistration_delay.timeout_seconds' | |
Value: '30' | |
# Redirect to SSL | |
MasterELBListener: # This is the ALB Listener used to access the Jenkins Master | |
Type: AWS::ElasticLoadBalancingV2::Listener | |
Properties: | |
DefaultActions: | |
- Type: "redirect" | |
RedirectConfig: | |
Protocol: "HTTPS" | |
Port: "443" | |
Host: "#{host}" | |
Path: "/#{path}" | |
Query: "#{query}" | |
StatusCode: "HTTP_301" | |
LoadBalancerArn: !Ref MasterELB | |
Port: 80 | |
Protocol: HTTP | |
MasterHTTPSListener: # This is the HTTPS ALB Listener used to access the Jenkins Master | |
Type: AWS::ElasticLoadBalancingV2::Listener | |
Properties: | |
Certificates: | |
- CertificateArn: !Ref CertificateArn | |
DefaultActions: | |
- Type: forward | |
TargetGroupArn: !Ref MasterELBTargetGroup | |
LoadBalancerArn: !Ref MasterELB | |
Port: 443 | |
Protocol: HTTPS | |
MasterIP: | |
Type: 'AWS::IAM::InstanceProfile' | |
Properties: | |
Roles: | |
- !Ref MasterIAMRole | |
MasterIAMRole: | |
Type: 'AWS::IAM::Role' | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: 'ec2.amazonaws.com' | |
Action: 'sts:AssumeRole' | |
ManagedPolicyArns: !If [HasManagedPolicyArns, !Split [',', !Ref ManagedPolicyArns], !Ref 'AWS::NoValue'] | |
Policies: | |
- !If | |
- HasSystemsManagerAccess | |
- PolicyName: ssm | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'ssmmessages:*' # SSM Agent by https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up-messageAPIs.html | |
- 'ssm:UpdateInstanceInformation' # SSM agent by https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up-messageAPIs.html | |
- 'ec2messages:*' # SSM Session Manager by https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up-messageAPIs.html | |
- 'ssm:ListAssociations' | |
- 'ssm:ListInstanceAssociations' | |
Resource: '*' | |
- !Ref 'AWS::NoValue' | |
- PolicyName: cloudwatch | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Sid: write | |
Effect: Allow | |
Action: 'cloudwatch:PutMetricData' | |
Resource: '*' | |
- PolicyName: autoscaling | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Sid: write | |
Effect: Allow | |
Action: | |
- 'autoscaling:CompleteLifecycleAction' | |
- 'cloudformation:SignalResource' | |
Resource: '*' | |
- PolicyName: logs | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'logs:CreateLogGroup' | |
- 'logs:CreateLogStream' | |
- 'logs:PutLogEvents' | |
- 'logs:DescribeLogStreams' | |
Resource: !GetAtt 'MasterLogs.Arn' | |
- PolicyName: sts | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: 'sts:AssumeRole' | |
Resource: '*' | |
MasterIAMPolicySSHAccess: | |
Type: 'AWS::IAM::Policy' | |
Condition: HasIAMUserSSHAccess | |
Properties: | |
Roles: | |
- !Ref MasterIAMRole | |
PolicyName: iam | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'iam:ListUsers' | |
Resource: | |
- '*' | |
- Effect: Allow | |
Action: | |
- 'iam:ListSSHPublicKeys' | |
- 'iam:GetSSHPublicKey' | |
Resource: | |
- !Sub 'arn:aws:iam::${AWS::AccountId}:user/*' | |
MasterSG: | |
Type: 'AWS::EC2::SecurityGroup' | |
Properties: | |
GroupDescription: 'crucible-master' | |
VpcId: {'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC'} | |
SecurityGroupIngress: | |
- SourceSecurityGroupId: !Ref MasterELBSG | |
FromPort: 8060 | |
ToPort: 8060 | |
IpProtocol: tcp | |
MasterSGInSSHWorld: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Condition: HasNotSSHBastionSecurityGroup | |
Properties: | |
GroupId: !Ref MasterSG | |
IpProtocol: tcp | |
FromPort: 22 | |
ToPort: 22 | |
CidrIp: '51.19.124.4/32' | |
MasterLogs: | |
Type: 'AWS::Logs::LogGroup' | |
Properties: | |
RetentionInDays: !Ref MasterLogsRetentionInDays | |
MasterLC: | |
Type: 'AWS::AutoScaling::LaunchConfiguration' | |
Properties: | |
IamInstanceProfile: !Ref MasterIP | |
InstanceType: !Ref MasterInstanceType | |
KeyName: !If [HasKeyName, !Ref KeyName, !Ref 'AWS::NoValue'] | |
SecurityGroups: | |
- !Ref MasterSG | |
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI] | |
BlockDeviceMappings: | |
- DeviceName: /dev/xvda | |
Ebs: | |
VolumeSize: !Ref MasterVolumeSize | |
VolumeType: gp2 | |
UserData: | |
'Fn::Base64': !Sub | | |
#!/bin/bash -x | |
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource MasterLC --region ${AWS::Region} | |
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MasterASG --region ${AWS::Region} | |
Metadata: | |
'AWS::CloudFormation::Init': | |
configSets: | |
default: [awslogs, !If [HasIAMUserSSHAccess, ssh-access, !Ref 'AWS::NoValue'], mount, extras, install, installFisheye, setup, custom] | |
awslogs: | |
packages: | |
yum: | |
awslogs: [] | |
files: | |
'/etc/awslogs/awscli.conf': | |
content: !Sub | | |
[default] | |
region = ${AWS::Region} | |
[plugins] | |
cwlogs = cwlogs | |
mode: '000644' | |
owner: root | |
group: root | |
'/etc/awslogs/awslogs.conf': | |
content: !Sub | | |
[general] | |
state_file = /var/lib/awslogs/agent-state | |
[/var/log/amazon/ssm/amazon-ssm-agent.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/amazon/ssm/amazon-ssm-agent.log | |
log_stream_name = {instance_id}/var/log/amazon/ssm/amazon-ssm-agent.log | |
log_group_name = ${MasterLogs} | |
[/var/log/amazon/ssm/errors.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/amazon/ssm/errors.log | |
log_stream_name = {instance_id}/var/log/amazon/ssm/errors.log | |
log_group_name = ${MasterLogs} | |
[/var/log/audit/audit.log] | |
file = /var/log/audit/audit.log | |
log_stream_name = {instance_id}/var/log/audit/audit.log | |
log_group_name = ${MasterLogs} | |
[/var/log/awslogs.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/awslogs.log | |
log_stream_name = {instance_id}/var/log/awslogs.log | |
log_group_name = ${MasterLogs} | |
[/var/log/boot.log] | |
file = /var/log/boot.log | |
log_stream_name = {instance_id}/var/log/boot.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cfn-hup.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-hup.log | |
log_stream_name = {instance_id}/var/log/cfn-hup.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cfn-init-cmd.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-init-cmd.log | |
log_stream_name = {instance_id}/var/log/cfn-init-cmd.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cfn-init.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-init.log | |
log_stream_name = {instance_id}/var/log/cfn-init.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cfn-wire.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-wire.log | |
log_stream_name = {instance_id}/var/log/cfn-wire.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cloud-init-output.log] | |
file = /var/log/cloud-init-output.log | |
log_stream_name = {instance_id}/var/log/cloud-init-output.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cloud-init.log] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/cloud-init.log | |
log_stream_name = {instance_id}/var/log/cloud-init.log | |
log_group_name = ${MasterLogs} | |
[/var/log/cron] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/cron | |
log_stream_name = {instance_id}/var/log/cron | |
log_group_name = ${MasterLogs} | |
[/var/log/dmesg] | |
file = /var/log/dmesg | |
log_stream_name = {instance_id}/var/log/dmesg | |
log_group_name = ${MasterLogs} | |
[/var/log/grubby_prune_debug] | |
file = /var/log/grubby_prune_debug | |
log_stream_name = {instance_id}/var/log/grubby_prune_debug | |
log_group_name = ${MasterLogs} | |
[/var/log/maillog] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/maillog | |
log_stream_name = {instance_id}/var/log/maillog | |
log_group_name = ${MasterLogs} | |
[/var/log/messages] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/messages | |
log_stream_name = {instance_id}/var/log/messages | |
log_group_name = ${MasterLogs} | |
[/var/log/secure] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/secure | |
log_stream_name = {instance_id}/var/log/secure | |
log_group_name = ${MasterLogs} | |
[/var/log/yum.log] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/yum.log | |
log_stream_name = {instance_id}/var/log/yum.log | |
log_group_name = ${MasterLogs} | |
[/var/log/fisheye.out] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/lib/atlassian/application-data/fecru/var/log/fisheye.out | |
log_stream_name = {instance_id}/var/log/fisheye.out | |
log_group_name = ${MasterLogs} | |
mode: '000644' | |
owner: root | |
group: root | |
'/etc/awslogs/config/efs.conf': | |
content: !Sub | | |
[/var/log/amazon/efs/mount.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/amazon/efs/mount.log | |
log_stream_name = {instance_id}/var/log/amazon/efs/mount.log | |
log_group_name = ${MasterLogs} | |
mode: '000644' | |
owner: root | |
group: root | |
'/etc/awslogs/config/fisheye.conf': | |
content: !Sub | | |
[/var/atlassian/application-data/fecru/var/log] | |
datetime_format = %d %b %Y %H:%M:%S | |
multi_line_start_pattern = {datetime_format} | |
file = /var/atlassian/application-data/fecru/var/log/fisheye.out | |
log_stream_name = {instance_id}/var/atlassian/application-data/fecru/var/log/fisheye.out | |
log_group_name = ${MasterLogs} | |
mode: '000644' | |
owner: root | |
group: root | |
services: | |
sysvinit: | |
awslogsd: | |
enabled: true | |
ensureRunning: true | |
packages: | |
yum: | |
- awslogs | |
files: | |
- '/etc/awslogs/awscli.conf' | |
- '/etc/awslogs/awslogs.conf' | |
- '/etc/awslogs/config/efs.conf' | |
- '/etc/awslogs/config/fisheye.conf' | |
ssh-access: | |
files: | |
'/opt/authorized_keys_command.sh': | |
content: | | |
#!/bin/bash -e | |
if [ -z "$1" ]; then | |
exit 1 | |
fi | |
UnsaveUserName="$1" | |
UnsaveUserName=${UnsaveUserName//".plus."/"+"} | |
UnsaveUserName=${UnsaveUserName//".equal."/"="} | |
UnsaveUserName=${UnsaveUserName//".comma."/","} | |
UnsaveUserName=${UnsaveUserName//".at."/"@"} | |
aws iam list-ssh-public-keys --user-name "$UnsaveUserName" --query "SSHPublicKeys[?Status == 'Active'].[SSHPublicKeyId]" --output text | while read -r KeyId; do | |
aws iam get-ssh-public-key --user-name "$UnsaveUserName" --ssh-public-key-id "$KeyId" --encoding SSH --query "SSHPublicKey.SSHPublicKeyBody" --output text | |
done | |
mode: '000755' | |
owner: root | |
group: root | |
'/opt/import_users.sh': | |
content: | | |
#!/bin/bash -e | |
aws iam list-users --query "Users[].[UserName]" --output text | while read User; do | |
SaveUserName="$User" | |
SaveUserName=${SaveUserName//"+"/".plus."} | |
SaveUserName=${SaveUserName//"="/".equal."} | |
SaveUserName=${SaveUserName//","/".comma."} | |
SaveUserName=${SaveUserName//"@"/".at."} | |
if [ "${#SaveUserName}" -le "32" ]; then | |
if ! id -u "$SaveUserName" >/dev/null 2>&1; then | |
#sudo will read each file in /etc/sudoers.d, skipping file names that end in ‘~’ or contain a ‘.’ character to avoid causing problems with package manager or editor temporary/backup files. | |
SaveUserFileName=$(echo "$SaveUserName" | tr "." " ") | |
/usr/sbin/useradd "$SaveUserName" | |
echo "$SaveUserName ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$SaveUserFileName" | |
fi | |
else | |
echo "Can not import IAM user ${SaveUserName}. User name is longer than 32 characters." | |
fi | |
done | |
mode: '000755' | |
owner: root | |
group: root | |
'/etc/cron.d/import_users': | |
content: | | |
*/10 * * * * root /opt/import_users.sh | |
mode: '000644' | |
owner: root | |
group: root | |
commands: | |
'a_configure_sshd_command': | |
command: 'sed -e ''/AuthorizedKeysCommand / s/^#*/#/'' -i /etc/ssh/sshd_config; echo -e ''\nAuthorizedKeysCommand /opt/authorized_keys_command.sh'' >> /etc/ssh/sshd_config' | |
test: '! grep -q ''^AuthorizedKeysCommand /opt/authorized_keys_command.sh'' /etc/ssh/sshd_config' | |
'b_configure_sshd_commanduser': | |
command: 'sed -e ''/AuthorizedKeysCommandUser / s/^#*/#/'' -i /etc/ssh/sshd_config; echo -e ''\nAuthorizedKeysCommandUser nobody'' >> /etc/ssh/sshd_config' | |
test: '! grep -q ''^AuthorizedKeysCommandUser nobody'' /etc/ssh/sshd_config' | |
'c_import_users': | |
command: './import_users.sh' | |
cwd: '/opt' | |
services: | |
sysvinit: | |
sshd: | |
enabled: true | |
ensureRunning: true | |
commands: | |
- 'a_configure_sshd_command' | |
- 'b_configure_sshd_commanduser' | |
mount: | |
packages: | |
yum: | |
'amazon-efs-utils': [] | |
commands: | |
'a_useradd': | |
command: 'adduser -s /bin/false -d /opt/fecru-4.8.1 -M -c ''Fisheye Crucible Server'' fisheye' | |
test: 'if grep -q fisheye: /etc/passwd; then exit 1; else exit 0; fi' | |
'b_mount': | |
command: !Sub 'mkdir -p /var/lib/atlassian/application-data/fecru && chown -R fisheye:fisheye /var/lib/atlassian && echo "${MasterStorage}:/ /var/lib/atlassian efs tls,_netdev 0 0" >> /etc/fstab && mount -a -t efs' | |
test: '[ ! -d /var/atlassian ]' | |
extras: | |
commands: | |
'a_enable_corretto8': | |
command: 'amazon-linux-extras enable corretto8' | |
test: "! grep -Fxq '[amzn2extra-corretto8]' /etc/yum.repos.d/amzn2-extras.repo" | |
install: | |
packages: | |
yum: | |
'java-1.8.0-amazon-corretto': [] | |
files: | |
'/etc/cfn/cfn-hup.conf': | |
content: !Sub | | |
[main] | |
stack=${AWS::StackId} | |
region=${AWS::Region} | |
interval=1 | |
mode: '000400' | |
owner: root | |
group: root | |
'/etc/cfn/hooks.d/cfn-auto-reloader.conf': | |
content: !Sub | | |
[cfn-auto-reloader-hook] | |
triggers=post.update | |
path=Resources.MasterLC.Metadata.AWS::CloudFormation::Init | |
action=/opt/aws/bin/cfn-init --verbose --stack=${AWS::StackName} --region=${AWS::Region} --resource=MasterLC | |
runas=root | |
services: | |
sysvinit: | |
cfn-hup: | |
enabled: true | |
ensureRunning: true | |
files: | |
- '/etc/cfn/cfn-hup.conf' | |
- '/etc/cfn/hooks.d/cfn-auto-reloader.conf' | |
amazon-ssm-agent: | |
enabled: !If [HasSystemsManagerAccess, true, false] | |
ensureRunning: !If [HasSystemsManagerAccess, true, false] | |
installFisheye: | |
commands: | |
InstallFisheye01: | |
command: >- | |
cd /tmp | |
InstallFisheye02: | |
command: >- | |
wget https://www.atlassian.com/software/crucible/downloads/binary/crucible-4.8.1.zip | |
InstallFisheye03: | |
command: >- | |
unzip -d /opt/ crucible-4.8.1.zip | |
InstallFisheye04: | |
command: >- | |
chown -R fisheye:fisheye /opt/fecru-4.8.1 | |
setup: | |
files: | |
'/lib/systemd/system/fisheye.service': | |
content: | | |
[Unit] | |
Description=Fisheye the on-premise source code repository browser for enterprise teams | |
After=syslog.target network.target | |
[Service] | |
Type=forking | |
User=fisheye | |
ExecStart=/opt/fecru-4.8.1/bin/fisheyectl.sh start | |
ExecStop=/opt/fecru-4.8.1/bin/fisheyectl.sh stop | |
[Install] | |
WantedBy=multi-user.target | |
mode: '000700' | |
owner: root | |
group: root | |
commands: | |
'a_systemctl_reload': | |
command: 'systemctl daemon-reload' | |
# TODO: DO NOT USE /tmp directory. Use some other permanent ec2-user readable directory. | |
test: '[ ! -f /var/lib/atlassian/setup_done.txt ]' | |
'b_systemctl_enable_fisheye': | |
command: 'systemctl enable fisheye' | |
test: '[ ! -f /var/lib/atlassian/setup_done.txt ]' | |
'c_systemctl_start_fisheye': | |
command: 'systemctl start fisheye' | |
test: '[ ! -f /var/lib/atlassian/setup_done.txt ]' | |
'd_await_fisheye': | |
command: 'until $(curl -s -m 60 -o /dev/null -I -f --url "http://localhost:8060"); do printf "."; sleep 1; done' | |
test: '[ ! -f /var/lib/atlassian/setup_done.txt ]' | |
'z_create_setup_done_file': | |
command: 'echo "Setup done. Do not delete this file." > /var/lib/atlassian/setup_done.txt' | |
test: '[ ! -f /var/lib/atlassian/setup_done.txt ]' | |
custom: | |
packages: | |
yum: | |
git: [] | |
subversion: [] | |
MasterASG: | |
Type: 'AWS::AutoScaling::AutoScalingGroup' | |
DependsOn: | |
- MasterStorageMountTargetA | |
- MasterStorageMountTargetB | |
Properties: | |
LaunchConfigurationName: !Ref MasterLC | |
MinSize: '1' | |
MaxSize: '1' | |
HealthCheckGracePeriod: 1800 | |
HealthCheckType: ELB | |
NotificationConfigurations: !If | |
- HasAlertTopic | |
- - NotificationTypes: | |
- 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR' | |
- 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR' | |
TopicARN: {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
- [] | |
VPCZoneIdentifier: | |
- {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetA${MasterSubnetsReach}'} | |
- {'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetB${MasterSubnetsReach}'} | |
TargetGroupARNs: | |
- !Ref MasterELBTargetGroup | |
Tags: | |
- Key: Name | |
Value: 'crucible-master' | |
PropagateAtLaunch: true | |
MetricsCollection: | |
- Fn::If: | |
- HasMasterMetrics | |
- Granularity: 1Minute | |
- !Ref 'AWS::NoValue' | |
CreationPolicy: | |
ResourceSignal: | |
Timeout: PT15M | |
UpdatePolicy: | |
AutoScalingRollingUpdate: | |
PauseTime: PT15M | |
SuspendProcesses: | |
- HealthCheck | |
- ReplaceUnhealthy | |
- AZRebalance | |
- AlarmNotification | |
- ScheduledActions | |
WaitOnResourceSignals: true | |
MasterCPUTooHighAlarm: | |
Condition: HasAlertTopic | |
Type: 'AWS::CloudWatch::Alarm' | |
Properties: | |
AlarmDescription: 'Master average CPU utilization over last 10 minutes higher than 80%' | |
Namespace: 'AWS/EC2' | |
MetricName: CPUUtilization | |
Statistic: Average | |
Period: 600 | |
EvaluationPeriods: 1 | |
ComparisonOperator: GreaterThanThreshold | |
Threshold: 80 | |
AlarmActions: | |
- {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'} | |
Dimensions: | |
- Name: AutoScalingGroupName | |
Value: !Ref MasterASG | |
LambdaRole: | |
Condition: HasEFSProvisionedThroughput | |
Type: 'AWS::IAM::Role' | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: 'lambda.amazonaws.com' | |
Action: 'sts:AssumeRole' | |
LambdaPolicy: | |
Condition: HasEFSProvisionedThroughput | |
Type: 'AWS::IAM::Policy' | |
Properties: | |
Roles: | |
- !Ref LambdaRole | |
PolicyName: lambda | |
PolicyDocument: | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'logs:CreateLogStream' | |
- 'logs:PutLogEvents' | |
Resource: !GetAtt 'LambdaLogGroup.Arn' | |
LambdaFunction: # needs no monitoring because it is used as a custom resource | |
Condition: HasEFSProvisionedThroughput | |
Type: 'AWS::Lambda::Function' | |
Properties: | |
Code: | |
ZipFile: | | |
'use strict'; | |
const response = require('cfn-response'); | |
exports.handler = (event, context, cb) => { | |
const throughput = parseInt(event.ResourceProperties.ThroughputInMibps, 10); | |
const threshold = Math.round(throughput * 1048576 * 600 * 0.9); | |
response.send(event, context, response.SUCCESS, {Threshold: threshold}); | |
}; | |
Handler: 'index.handler' | |
MemorySize: 128 | |
Role: !GetAtt 'LambdaRole.Arn' | |
Runtime: 'nodejs12.x' | |
Timeout: 60 | |
LambdaLogGroup: | |
Condition: HasEFSProvisionedThroughput | |
Type: 'AWS::Logs::LogGroup' | |
Properties: | |
LogGroupName: !Sub '/aws/lambda/${LambdaFunction}' | |
RetentionInDays: !Ref MasterLogsRetentionInDays | |
MaxThroughputCalculator: | |
Condition: HasEFSProvisionedThroughput | |
Type: 'Custom::MaxThroughputCalculator' | |
DependsOn: | |
- LambdaLogGroup | |
- LambdaPolicy | |
Version: '1.0' | |
Properties: | |
ThroughputInMibps: !Ref EFSProvisionedThroughputInMibps | |
ServiceToken: !GetAtt 'LambdaFunction.Arn' | |
BackupVault: # cannot be deleted with data | |
Condition: HasEFSBackupRetentionPeriod | |
Type: 'AWS::Backup::BackupVault' | |
Properties: | |
BackupVaultName: !Ref 'AWS::StackName' | |
Notifications: !If [HasAlertTopic, {BackupVaultEvents: [BACKUP_JOB_STARTED, BACKUP_JOB_COMPLETED, RESTORE_JOB_STARTED, RESTORE_JOB_COMPLETED, RECOVERY_POINT_MODIFIED], SNSTopicArn: {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}}, !Ref 'AWS::NoValue'] | |
BackupPlan: | |
Condition: HasEFSBackupRetentionPeriod | |
Type: 'AWS::Backup::BackupPlan' | |
Properties: | |
BackupPlan: | |
BackupPlanName: !Ref 'AWS::StackName' | |
BackupPlanRule: | |
- CompletionWindowMinutes: 1440 | |
Lifecycle: | |
DeleteAfterDays: !Ref EFSBackupRetentionPeriod | |
RuleName: !Ref 'AWS::StackName' | |
ScheduleExpression: !Ref EFSBackupScheduleExpression | |
StartWindowMinutes: 60 | |
TargetBackupVault: !Ref BackupVault | |
BackupRole: | |
Condition: HasEFSBackupRetentionPeriod | |
Type: 'AWS::IAM::Role' | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: 'backup.amazonaws.com' | |
Action: 'sts:AssumeRole' | |
Policies: | |
- PolicyName: backup | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'elasticfilesystem:Backup' | |
- 'elasticfilesystem:DescribeTags' | |
Resource: !Sub 'arn:${AWS::Partition}:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${MasterStorage}' | |
BackupSelection: | |
Condition: HasEFSBackupRetentionPeriod | |
Type: 'AWS::Backup::BackupSelection' | |
Properties: | |
BackupPlanId: !Ref BackupPlan | |
BackupSelection: | |
IamRoleArn: !GetAtt 'BackupRole.Arn' | |
Resources: | |
- !Sub 'arn:${AWS::Partition}:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${MasterStorage}' | |
SelectionName: !Ref 'AWS::StackName' | |
Outputs: | |
TemplateID: | |
Description: 'template id.' | |
Value: 'crucible/fisheye-crucible' | |
TemplateVersion: | |
Description: 'template version.' | |
Value: '__VERSION__' | |
StackName: | |
Description: 'Stack name.' | |
Value: !Sub '${AWS::StackName}' | |
DNSName: | |
Description: 'The DNS name for the Crucible load balancer.' | |
Value: !GetAtt 'MasterELB.DNSName' | |
Export: | |
Name: !Sub '${AWS::StackName}-DNSName' | |
URL: | |
Description: 'URL to the Crucible Master.' | |
Value: !Sub 'https://${MasterELB.DNSName}' | |
Export: | |
Name: !Sub '${AWS::StackName}-URL' | |
MasterIAMRole: | |
Description: 'Use this IAm Role to reference API calls from the Crucible master' | |
Value: !GetAtt 'MasterIAMRole.Arn' | |
Export: | |
Name: !Sub '${AWS::StackName}-MasterIAMRole' | |
MasterELBSG: | |
Description: 'Master ELB SG' | |
Value: !GetAtt 'MasterELBSG.GroupId' | |
Export: | |
Name: !Sub '${AWS::StackName}-MasterELBSG' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment