# CloudFormation Organization # - master # - logging # - config rules # - vpc management # - vpc production # - vpc networking (peering) # - bastion # - application # - encrypted elb # - copy lambda # - configure ssl # - acm/route53 # - database AWSTemplateFormatVersion: 2010-09-09 Description: 'Main template for deploying example HITRUST CSF Quick Start. Creates VPC, 3-tier web app, and logging. (qs-1q77hsjug)' Metadata: cfn-lint: config: ignore_checks: - W9006 - W9901 QuickStartDocumentation: EntrypointName: "Parameters for deploying into new VPCs" AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network Configuration Parameters: - AvailabilityZones - BastionAccessCidr - SourceCidr - Label: default: Logging Configuration Parameters: - ConfigRecorder - ConfigDeliveryChannel - Label: default: Server DNS configuration Parameters: - AWSPublicFQDN - AWSHostedZoneID - SSLCertificateARN - Label: default: Security Configuration Parameters: - DBPassword - BastionKeyPairName - KeyPairName - Label: default: AWS Quick Start Configuration Parameters: - QSS3BucketName - QSS3BucketRegion - QSS3KeyPrefix - QSTagKey - QSTagValue ParameterLabels: AWSHostedZoneID: default: DNS Zone ID AWSPublicFQDN: default: Full DNS Name for Web App AvailabilityZones: default: Availability Zones BastionAccessCidr: default: CIDR to access bastion BastionKeyPairName: default: Bastion key pair ConfigRecorder: default: AWS Config Recorder Name ConfigDeliveryChannel: default: AWS Config Delivery Channel Name DBPassword: default: Database Password KeyPairName: default: EC2 Key Pair (App) QSS3BucketName: default: Quick Start S3 Bucket Name QSS3BucketRegion: default: Quick Start S3 bucket region QSS3KeyPrefix: default: Quick Start S3 Key Prefix QSTagKey: default: Quick Start Tag key QSTagValue: default: Quick Start Tag value SSLCertificateARN: default: SSL Certificate ARN (Requires matching DNS name) SourceCidr: default: Source CIDR for access Parameters: AWSHostedZoneID: Description: DNS Zone ID to contain the server's DNS entry. Type: AWS::Route53::HostedZone::Id AWSPublicFQDN: Description: Web app will be reachable at this address. Type: String AvailabilityZones: Description: 'List of Availability Zones to use for the subnets in the VPC. You must use two Availabilty Zones. The Quick Start preserves the logical order you specify.' Type: List BastionAccessCidr: AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$" ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x. Description: IP address/range to allow access to bastion host from Type: String BastionKeyPairName: Type: AWS::EC2::KeyPair::KeyName Description: Name of an existing EC2 KeyPair to enable SSH access to Bastion Host ConstraintDescription: Must be the name of an existing EC2 Key Pair ConfigRecorder: Type: String Default: "" Description: Config Recorder in your AWS Region. Leaving empty will try to create a new recorder. ConfigDeliveryChannel: Type: String Default: "" Description: Config Delivery Channel in your AWS Region. Leaving empty will try to create a new recorder. Required if you specify Config Recorder DBPassword: Description: Mixed alphanumeric and must be between 8 and 28 characters and contain at least one capital letter NoEcho: true Type: String MinLength: 8 MaxLength: 28 AllowedPattern: '[a-zA-Z0-9!^*\-_+]*' ConstraintDescription: Can only contain alphanumeric characters or the following special characters !^*-_+, between 8 and 28 characters KeyPairName: Type: AWS::EC2::KeyPair::KeyName Description: Name of an existing EC2 KeyPair to enable SSH access to app servers ConstraintDescription: Must be the name of an existing EC2 Key Pair QSS3BucketName: AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-.]*[0-9a-zA-Z])*$ ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, periods (.), and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Type: String QSS3BucketRegion: Default: 'us-east-1' Description: 'The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value.' Type: String QSS3KeyPrefix: AllowedPattern: ^[0-9a-zA-Z-/]*$ ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). Default: quickstart-hitrust-csf/ Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). Type: String QSTagKey: Type: String Description: Tag key to identify resources from this Quick Start Default: QuickStartID QSTagValue: Type: String Description: Tag value to identify resources from this Quick Start Default: quickstart-hitrust-csf SSLCertificateARN: Type: String Default: "" Description: The Amazon Resource Name for the existing SSL cert you wish to use; empty for none. If empty, will create as part of Quick Start SourceCidr: AllowedPattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$" ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x. Description: IP address/range to allow access to web app from Type: String Mappings: Networking: ProductionCIDR: Private1A: 10.100.0.0/20 Private1B: 10.100.16.0/20 Private2A: 10.100.32.0/20 Private2B: 10.100.48.0/20 Public1: 10.100.100.0/24 Public2: 10.100.101.0/24 VPC: 10.100.0.0/16 ManagementCIDR: Private1A: 10.101.0.0/20 Private1B: 10.101.16.0/20 Private2A: 10.101.32.0/20 Private2B: 10.101.48.0/20 Public1: 10.101.100.0/24 Public2: 10.101.101.0/24 VPC: 10.101.0.0/16 Bastion: InstanceType: t2.medium Conditions: UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] Resources: # Need Config Rules Logging: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/logging.template - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: ConfigRecorderName: !Ref ConfigRecorder ConfigDeliveryChannelName: !Ref ConfigDeliveryChannel QSS3BucketName: !Ref QSS3BucketName QSS3BucketRegion: !Ref QSS3BucketRegion QSS3KeyPrefix: !Ref QSS3KeyPrefix QSTagKey: !Ref QSTagKey QSTagValue: !Sub ${QSTagValue}-${AWS::StackName} Tags: - Key: !Ref QSTagKey Value: !Sub ${QSTagValue}-${AWS::StackName} ProductionVpc: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: AvailabilityZones: !Join [ "," , !Ref AvailabilityZones ] CreateAdditionalPrivateSubnets: 'true' CreatePrivateSubnets: 'true' NumberOfAZs: '2' PrivateSubnet1ACIDR: !FindInMap [ Networking, ProductionCIDR, Private1A ] PrivateSubnet1BCIDR: !FindInMap [ Networking, ProductionCIDR, Private1B ] PrivateSubnet2ACIDR: !FindInMap [ Networking, ProductionCIDR, Private2A ] PrivateSubnet2BCIDR: !FindInMap [ Networking, ProductionCIDR, Private2B ] PublicSubnet1CIDR: !FindInMap [ Networking, ProductionCIDR, Public1 ] PublicSubnet2CIDR: !FindInMap [ Networking, ProductionCIDR, Public2 ] PublicSubnetTag1: !Sub ${QSTagKey}=${QSTagValue}-${AWS::StackName} PrivateSubnetATag1: !Sub ${QSTagKey}=${QSTagValue}-${AWS::StackName} PrivateSubnetBTag1: !Sub ${QSTagKey}=${QSTagValue}-${AWS::StackName} VPCCIDR: !FindInMap [ Networking, ProductionCIDR, VPC ] Tags: - Key: !Ref QSTagKey Value: !Sub ${QSTagValue}-${AWS::StackName} ManagementVpc: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: AvailabilityZones: !Join [ "," , !Ref AvailabilityZones ] CreateAdditionalPrivateSubnets: 'true' CreatePrivateSubnets: 'true' NumberOfAZs: '2' PrivateSubnet1ACIDR: !FindInMap [ Networking, ManagementCIDR, Private1A ] PrivateSubnet1BCIDR: !FindInMap [ Networking, ManagementCIDR, Private1B ] PrivateSubnet2ACIDR: !FindInMap [ Networking, ManagementCIDR, Private2A ] PrivateSubnet2BCIDR: !FindInMap [ Networking, ManagementCIDR, Private2B ] PublicSubnet1CIDR: !FindInMap [ Networking, ManagementCIDR, Public1 ] PublicSubnet2CIDR: !FindInMap [ Networking, ManagementCIDR, Public2 ] PublicSubnetTag1: !Sub ${QSTagKey}=${QSTagValue}-${AWS::StackName} PrivateSubnetATag1: !Sub ${QSTagKey}=${QSTagValue}-${AWS::StackName} PrivateSubnetBTag1: !Sub ${QSTagKey}=${QSTagValue}-${AWS::StackName} VPCCIDR: !FindInMap [ Networking, ManagementCIDR, VPC ] Tags: - Key: !Ref QSTagKey Value: !Sub ${QSTagValue}-${AWS::StackName} VpcNetworking: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/vpc-networking.template - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: ProductionVpcId: !GetAtt ProductionVpc.Outputs.VPCID ProductionVpcCidr: !GetAtt ProductionVpc.Outputs.VPCCIDR ProductionRouteTablePrivateA: !GetAtt ProductionVpc.Outputs.PrivateSubnet1ARouteTable ProductionRouteTablePrivateB: !GetAtt ProductionVpc.Outputs.PrivateSubnet2ARouteTable ProductionRouteTablePublic: !GetAtt ProductionVpc.Outputs.PublicSubnetRouteTable ManagementVpcId: !GetAtt ManagementVpc.Outputs.VPCID ManagementVpcCidr: !GetAtt ManagementVpc.Outputs.VPCCIDR ManagementRouteTablePrivateA: !GetAtt ManagementVpc.Outputs.PrivateSubnet1ARouteTable ManagementRouteTablePrivateB: !GetAtt ManagementVpc.Outputs.PrivateSubnet2ARouteTable ManagementRouteTablePublic: !GetAtt ManagementVpc.Outputs.PublicSubnetRouteTable QSTagKey: !Ref QSTagKey QSTagValue: !Sub ${QSTagValue}-${AWS::StackName} Tags: - Key: !Ref QSTagKey Value: !Sub ${QSTagValue}-${AWS::StackName} Bastion: Type: AWS::CloudFormation::Stack DependsOn: - VpcNetworking Properties: TemplateURL: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-linux-bastion/templates/linux-bastion.template - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: BastionInstanceType: !FindInMap [ Networking, Bastion, InstanceType ] EnableBanner: 'false' KeyPairName: !Ref BastionKeyPairName RemoteAccessCIDR: !Ref BastionAccessCidr PublicSubnet1ID: !GetAtt ManagementVpc.Outputs.PublicSubnet1ID PublicSubnet2ID: !GetAtt ManagementVpc.Outputs.PublicSubnet2ID QSS3BucketName: !Ref QSS3BucketName QSS3BucketRegion: !Ref QSS3BucketRegion QSS3KeyPrefix: !Sub ${QSS3KeyPrefix}submodules/quickstart-linux-bastion/ VPCID: !GetAtt ManagementVpc.Outputs.VPCID Tags: - Key: !Ref QSTagKey Value: !Sub ${QSTagValue}-${AWS::StackName} Application: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/application.template - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: AWSHostedZoneID: !Ref AWSHostedZoneID AWSPublicFQDN: !Ref AWSPublicFQDN BastionSecurityGroup: !GetAtt Bastion.Outputs.BastionSecurityGroupID DBPassword: !Ref DBPassword KeyPairName: !Ref KeyPairName LogBucket: !GetAtt Logging.Outputs.LogBucket PublicSubnetIds: !Sub "${ProductionVpc.Outputs.PublicSubnet1ID},${ProductionVpc.Outputs.PublicSubnet2ID}" PrivateSubnetAppIds: !Sub "${ProductionVpc.Outputs.PrivateSubnet1AID},${ProductionVpc.Outputs.PrivateSubnet2AID}" PrivateSubnetDBIds: !Sub "${ProductionVpc.Outputs.PrivateSubnet1BID},${ProductionVpc.Outputs.PrivateSubnet2BID}" QSS3BucketName: !Ref QSS3BucketName QSS3BucketRegion: !Ref QSS3BucketRegion QSS3KeyPrefix: !Ref QSS3KeyPrefix QSTagKey: !Ref QSTagKey QSTagValue: !Sub ${QSTagValue}-${AWS::StackName} SourceCidr: !Ref SourceCidr SSLCertificateARN: !Ref SSLCertificateARN VpcCidr: !GetAtt ProductionVpc.Outputs.VPCCIDR VpcId: !GetAtt ProductionVpc.Outputs.VPCID Tags: - Key: !Ref QSTagKey Value: !Sub ${QSTagValue}-${AWS::StackName} Outputs: ManagementVpcId: Description: Management VPC ID Value: !GetAtt ManagementVpc.Outputs.VPCID ProductionVpcId: Description: Production VPC ID Value: !GetAtt ProductionVpc.Outputs.VPCID ApplicationURL: Description: Web App URL Value: !GetAtt Application.Outputs.ApplicationURL LandingPageURL: Description: Landing Page Value: !GetAtt Application.Outputs.LandingPageURL