cia-dist-cloudformation/src/main/resources/cia-dist-cloudformation.json
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "CIA CloudFormation runtime",
"Parameters": {
"WebServerInstanceType": {
"Description": "WebServer Server EC2 instance type",
"Type": "String",
"Default": "t4g.large",
"AllowedValues": [
"t4g.micro",
"t4g.small",
"t4g.medium",
"t4g.large",
"t4g.xlarge",
"t4g.2xlarge",
"m6g.large",
"m6g.xlarge",
"m6g.2xlarge",
"m6g.8xlarge",
"m6g.4xlarge",
"m6g.12xlarge",
"m6g.16xlarge",
"c7g.large",
"c7g.xlarge",
"c7g.2xlarge",
"c7g.4xlarge",
"c7g.8xlarge",
"c7g.12xlarge",
"c7g.16xlarge"
],
"ConstraintDescription": "must be a valid EC2 instance type."
},
"WebServerAmi": {
"Description": "Web server ami ubuntu arm 22.04, recommend ebs encrypted ami based on ubuntu hvm-ssd server",
"Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
"Default": "/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id"
},
"WebServerCount": {
"Description": "Number of EC2 instances to launch for the WebServer server",
"Type": "Number",
"Default": "2"
},
"WebServerAppLogAppender": {
"Description": "App log output appender console/elasticsearch/cloudwatch/awslogs/kinesis",
"Type": "String",
"Default": "cloudwatch"
},
"DomainNamePrefix": {
"Description": "Domain name prefix (optional), used to setup route53 dns",
"Type": "String",
"Default": "cia"
},
"DomainName": {
"Description": "Domain name (optional), used to setup route53 dns",
"Type": "String",
"Default": "hack23.com"
},
"DBEncryptionKmsAlias": {
"Description": "The alias for Key Management Service encryption key alias",
"Type": "String",
"Default": ""
},
"DBName": {
"Default": "pgdb",
"Description": "The database name",
"Type": "String",
"MinLength": "1",
"MaxLength": "8",
"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription": "must begin with a letter and contain only alphanumeric characters."
},
"DBUsername": {
"Default": "root",
"NoEcho": "true",
"Description": "The database admin account username",
"Type": "String",
"MinLength": "1",
"MaxLength": "16",
"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription": "must begin with a letter and contain only alphanumeric characters."
},
"DBPassword": {
"Default": "root1234",
"NoEcho": "true",
"Description": "The database admin account password",
"Type": "String",
"MinLength": "8"
},
"RotationLambda": {
"Description": "arn of RotationLambda used to rotate password",
"Default": "",
"Type": "String"
},
"DBSnapshotName": {
"Description": "The name of a DB snapshot (optional, if arn:aws:rds:eu-west-1:172017021075:snapshot:cia-demo-20170711 supplied DBUsername,DBPassword need to eris,discord23)",
"Default": "",
"Type": "String"
},
"DebPackageUrl": {
"Default": "https://repo1.maven.org/maven2/com/hack23/cia/cia-dist-deb/2022.12.26/cia-dist-deb-2022.12.26.deb",
"Description": "The debian package url",
"Type": "String",
"MinLength": "8"
},
"DBClass": {
"Default": "db.t4g.medium",
"Description": "Database instance class",
"Type": "String",
"AllowedValues": [
"db.t4g.micro",
"db.t4g.small",
"db.t4g.medium",
"db.t4g.large",
"db.t4g.xlarge",
"db.t4g.2xlarge",
"db.m6g.large",
"db.m6g.xlarge",
"db.m6g.2xlarge",
"db.m6g.4xlarge",
"db.m6g.12xlarge",
"db.m6g.16xlarge",
"db.r6g.large",
"db.r6g.xlarge",
"db.r6g.2xlarge",
"db.r6g.4xlarge",
"db.r6g.8xlarge",
"db.r6g.16xlarge"
],
"ConstraintDescription": "must select a valid database instance type."
},
"DBAllocatedStorage": {
"Default": "200",
"Description": "The size of the database (Gb)",
"Type": "Number",
"MinValue": "100",
"MaxValue": "6144",
"ConstraintDescription": "must be between 10+"
}
},
"Mappings": {
"SubnetConfig": {
"VPC": {
"CIDR": "10.40.0.0/16"
},
"Public": {
"CIDR": "10.40.10.0/24"
},
"Public2": {
"CIDR": "10.40.11.0/24"
},
"Public3": {
"CIDR": "10.40.12.0/24"
},
"PrivateApp": {
"CIDR": "10.40.30.0/24"
},
"PrivateApp2": {
"CIDR": "10.40.31.0/24"
},
"PrivateApp3": {
"CIDR": "10.40.32.0/24"
},
"Private": {
"CIDR": "10.40.20.0/24"
},
"Private2": {
"CIDR": "10.40.21.0/24"
},
"Private3": {
"CIDR": "10.40.22.0/24"
}
},
"AWSRegionAvailabilityZone": {
"us-east-1": {
"FIRST": "us-east-1a",
"SECOND": "us-east-1b",
"THIRD": "us-east-1c"
},
"us-west-1": {
"FIRST": "us-west-1a",
"SECOND": "us-west-1b",
"THIRD": "us-west-1c"
},
"us-west-2": {
"FIRST": "us-west-2a",
"SECOND": "us-west-2b",
"THIRD": "us-west-2c"
},
"eu-west-1": {
"FIRST": "eu-west-1a",
"SECOND": "eu-west-1b",
"THIRD": "eu-west-1c"
},
"eu-north-1": {
"FIRST": "eu-north-1a",
"SECOND": "eu-north-1b",
"THIRD": "eu-north-1c"
},
"eu-central-1": {
"FIRST": "eu-central-1a",
"SECOND": "eu-central-1b",
"THIRD": "eu-central-1c"
},
"ap-northeast-1": {
"FIRST": "ap-northeast-1a",
"SECOND": "ap-northeast-1b",
"THIRD": "ap-northeast-1c"
},
"ap-southeast-1": {
"FIRST": "ap-southeast-1a",
"SECOND": "ap-southeast-1b",
"THIRD": "ap-southeast-1c"
},
"ap-southeast-2": {
"FIRST": "ap-southeast-2a",
"SECOND": "ap-southeast-2b",
"THIRD": "ap-southeast-2c"
},
"sa-east-1": {
"FIRST": "sa-east-1a",
"SECOND": "sa-east-1b",
"THIRD": "sa-east-1c"
},
"cn-north-1": {
"FIRST": "cn-north-1a",
"SECOND": "cn-north-1b",
"THIRD": "cn-north-1c"
}
}
},
"Conditions": {
"useDBSnapshot": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "DBSnapshotName"
},
""
]
}
]
},
"useDBEncryptionKmsAlias": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "DBEncryptionKmsAlias"
},
""
]
}
]
},
"useDomainName": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "DomainName"
},
""
]
}
]
},
"useRotationLambda": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "RotationLambda"
},
""
]
}
]
}
},
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"EnableDnsSupport": "true",
"EnableDnsHostnames": "true",
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"FlowLogsRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"vpc-flow-logs.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/"
}
},
"FlowLogsPolicy": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "FlowLogs",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams"
],
"Effect": "Allow",
"Resource": "*"
}
]
},
"Roles": [
{
"Ref": "FlowLogsRole"
}
]
},
"DependsOn": [
"FlowLogsRole"
]
},
"VPCFlowLog": {
"Type": "AWS::EC2::FlowLog",
"Properties": {
"DeliverLogsPermissionArn": {
"Fn::GetAtt": [
"FlowLogsRole",
"Arn"
]
},
"LogGroupName": {
"Fn::Join": [
"",
[
"VPCFlowLogsGroup",
"-",
{
"Ref": "AWS::StackName"
}
]
]
},
"ResourceId": {
"Ref": "VPC"
},
"ResourceType": "VPC",
"TrafficType": "ALL"
}
},
"ArtifactBucket": {
"Type": "AWS::S3::Bucket",
"DependsOn" : "LogsBucket",
"DeletionPolicy": "Retain",
"Properties": {
"AccessControl": "Private",
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"KMSMasterKeyID": {
"Ref": "ArtifactBucketEncryptionKey"
},
"SSEAlgorithm": "aws:kms"
}
}
]
},
"VersioningConfiguration": {
"Status": "Enabled"
},
"LifecycleConfiguration": {
"Rules": [
{
"Id": "Rule for log prefix",
"Status": "Enabled",
"Transitions": [
{
"TransitionInDays": 30,
"StorageClass": "STANDARD_IA"
},
{
"TransitionInDays": 90,
"StorageClass": "GLACIER"
}
],
"ExpirationInDays": 365
}
]
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
"IgnorePublicAcls": true,
"RestrictPublicBuckets": true
},
"LoggingConfiguration": {
"DestinationBucketName": { "Ref": "LogsBucket" },
"LogFilePrefix": "/logs/ArtifactBucket/"
},
"Tags": [
{
"Key": "DomainName",
"Value": {
"Ref": "DomainName"
}
},
{
"Key": "DataClassificationConfidentiality",
"Value": "Proprietary"
},
{
"Key": "DataClassificationIntegrity",
"Value": "Standard"
},
{
"Key": "DataClassificationAvailability",
"Value": "Standard"
}
]
}
},
"ArtifactBucketEncryptionKey": {
"Type": "AWS::KMS::Key",
"Properties": {
"Description": "Key used for Server Fleet Management Solution artifact bucket",
"Enabled": true,
"EnableKeyRotation": true,
"KeyPolicy": {
"Statement": [
{
"Sid": "manage-key",
"Action": [
"kms:*"
],
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root"
}
},
"Resource": "*"
},
{
"Sid": "ssm-access-policy-statement",
"Action": [
"kms:*"
],
"Effect": "Allow",
"Principal": {
"Service": "ssm.amazonaws.com"
},
"Resource": "*"
}
]
}
}
},
"ArtifactBucketEncryptionKeyAlias": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/ssm-bucket-encryption-key",
"TargetKeyId": {
"Ref": "ArtifactBucketEncryptionKey"
}
}
},
"ArtifactBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"DeletionPolicy": "Retain",
"Properties": {
"Bucket": {
"Ref": "ArtifactBucket"
},
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ArtifactBucketPermissionsCheck",
"Effect": "Allow",
"Resource": {
"Fn::Sub": "${ArtifactBucket.Arn}"
},
"Principal": {
"Service": "ssm.amazonaws.com"
},
"Action": [
"s3:GetBucketAcl"
]
},
{
"Sid": "ArtifactBucketDeliveryDenyHttp",
"Effect": "Deny",
"Principal": "*",
"Action": [ "s3:GetObject" ],
"Resource": {
"Fn::Sub": "${ArtifactBucket.Arn}/*"
},
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Sid": "ArtifactBucketDelivery",
"Effect": "Allow",
"Resource": {
"Fn::Sub": "${ArtifactBucket.Arn}/*"
},
"Principal": {
"Service": "ssm.amazonaws.com"
},
"Action": [
"s3:PutObject"
],
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
}
},
"MaintenanceWindowServiceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ssm.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AmazonSSMMaintenanceWindowRole"
],
"Policies": [
{
"PolicyName": "PassRole",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": [
"*"
]
}
]
}
}
]
}
},
"MaintenanceWindow": {
"Type": "AWS::SSM::MaintenanceWindow",
"Properties": {
"Description": "Daily Maintenance Window",
"AllowUnassociatedTargets": false,
"Cutoff": 0,
"Schedule": "rate(1 hour)",
"Duration": 1,
"Name": "hourly-patching"
}
},
"MaintenanceWindowTarget": {
"Type": "AWS::SSM::MaintenanceWindowTarget",
"Properties": {
"Description": "Server Fleet Management Solution Instances",
"WindowId": {
"Ref": "MaintenanceWindow"
},
"ResourceType": "INSTANCE",
"Targets": [
{
"Key": "tag:SystemPatchComplianceMaintenanceWindowActive",
"Values": [
"true"
]
}
]
}
},
"MaintenanceWindowTaskPatchBaselineInstall": {
"Type": "AWS::SSM::MaintenanceWindowTask",
"Properties": {
"Description": "Runs Server Fleet Management Solution patch baseline",
"ServiceRoleArn": {
"Fn::GetAtt": [
"MaintenanceWindowServiceRole",
"Arn"
]
},
"MaxErrors": 1,
"TaskArn": "AWS-RunPatchBaseline",
"MaxConcurrency": "100%",
"WindowId": {
"Ref": "MaintenanceWindow"
},
"Priority": 1,
"TaskType": "RUN_COMMAND",
"TaskInvocationParameters": {
"MaintenanceWindowRunCommandParameters": {
"Comment": "Runs patch baseline",
"TimeoutSeconds": 600,
"Parameters": {
"Operation": [
"Install"
]
},
"OutputS3BucketName": {
"Ref": "ArtifactBucket"
}
}
},
"Targets": [
{
"Values": [
{
"Ref": "MaintenanceWindowTarget"
}
],
"Key": "WindowTargetIds"
}
]
}
},
"MaintenanceWindowTaskPatchBaselineScan": {
"Type": "AWS::SSM::MaintenanceWindowTask",
"Properties": {
"Description": "Runs Server Fleet Management Solution patch baseline",
"ServiceRoleArn": {
"Fn::GetAtt": [
"MaintenanceWindowServiceRole",
"Arn"
]
},
"MaxErrors": 1,
"TaskArn": "AWS-RunPatchBaseline",
"MaxConcurrency": "100%",
"WindowId": {
"Ref": "MaintenanceWindow"
},
"Priority": 2,
"TaskType": "RUN_COMMAND",
"TaskInvocationParameters": {
"MaintenanceWindowRunCommandParameters": {
"Comment": "Runs patch baseline",
"TimeoutSeconds": 600,
"Parameters": {
"Operation": [
"Scan"
]
},
"OutputS3BucketName": {
"Ref": "ArtifactBucket"
}
}
},
"Targets": [
{
"Values": [
{
"Ref": "MaintenanceWindowTarget"
}
],
"Key": "WindowTargetIds"
}
]
}
},
"UpdateSSMAgent": {
"Type": "AWS::SSM::Association",
"Properties": {
"AssociationName": "UpdateSSMAgent",
"Name": "AWS-UpdateSSMAgent",
"Parameters": {
"allowDowngrade": [
"false"
]
},
"OutputLocation": {
"S3Location": {
"OutputS3BucketName": {
"Ref": "ArtifactBucket"
}
}
},
"ScheduleExpression": "rate(7 days)",
"Targets": [
{
"Key": "tag:UpdateSSMAgent",
"Values": [
"true"
]
}
]
}
},
"GatherSoftwareInventory": {
"Type": "AWS::SSM::Association",
"DependsOn": "ArtifactBucket",
"Properties": {
"AssociationName": "GatherSoftwareInventory",
"Name": "AWS-GatherSoftwareInventory",
"Parameters": {
"windowsUpdates": [
"Disabled"
],
"windowsRegistry": [
"Disabled"
],
"windowsRoles": [
"Disabled"
],
"services": [
"Disabled"
]
},
"OutputLocation": {
"S3Location": {
"OutputS3BucketName": {
"Ref": "ArtifactBucket"
}
}
},
"ScheduleExpression": "rate(1 hour)",
"Targets": [
{
"Key": "tag:GatherSoftwareInventory",
"Values": [
"true"
]
}
]
}
},
"PublicSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"FIRST"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Public",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PublicSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"SECOND"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Public2",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PublicSubnet3": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"THIRD"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Public3",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PrivateAppSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"FIRST"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "PrivateApp"
}
]
}
},
"PrivateAppSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"SECOND"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp2",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "PrivateApp"
}
]
}
},
"PrivateAppSubnet3": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"THIRD"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp3",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "PrivateApp"
}
]
}
},
"SgFormonitoringVPCEndpoint": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group to allow access to monitoring VPC Endpoint",
"SecurityGroupIngress": [
{
"Description": "vpc endpoint inbound access",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443"
}
],
"SecurityGroupEgress": [
{
"Description": "vpc endpoint outbound access",
"CidrIp": "0.0.0.0/0",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"monitoringVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"VpcEndpointType": "Interface",
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".monitoring"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"SubnetIds": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"PrivateDnsEnabled": true,
"SecurityGroupIds": [
{
"Ref": "SgFormonitoringVPCEndpoint"
}
]
}
},
"SgForlogsVPCEndpoint": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group to allow access to logs VPC Endpoint",
"SecurityGroupIngress": [
{
"Description": "vpc endpoint inbound access",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443"
}
],
"SecurityGroupEgress": [
{
"Description": "vpc endpoint outbound access",
"CidrIp": "0.0.0.0/0",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"logsVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"VpcEndpointType": "Interface",
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".logs"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"SubnetIds": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"PrivateDnsEnabled": true,
"SecurityGroupIds": [
{
"Ref": "SgForlogsVPCEndpoint"
}
]
}
},
"SgForssmVPCEndpoint": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group to allow access to ssm VPC Endpoint",
"SecurityGroupIngress": [
{
"Description": "vpc endpoint inbound access",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443"
}
],
"SecurityGroupEgress": [
{
"Description": "vpc endpoint outbound access",
"CidrIp": "0.0.0.0/0",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"ssmVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"VpcEndpointType": "Interface",
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".ssm"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"SubnetIds": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"PrivateDnsEnabled": true,
"SecurityGroupIds": [
{
"Ref": "SgForssmVPCEndpoint"
}
]
}
},
"SgForssmmessagesVPCEndpoint": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group to allow access to ssmmessages VPC Endpoint",
"SecurityGroupIngress": [
{
"Description": "vpc endpoint inbound access",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443"
}
],
"SecurityGroupEgress": [
{
"Description": "vpc endpoint outbound access",
"CidrIp": "0.0.0.0/0",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"ssmmessagesVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"VpcEndpointType": "Interface",
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".ssmmessages"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"SubnetIds": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"PrivateDnsEnabled": true,
"SecurityGroupIds": [
{
"Ref": "SgForssmmessagesVPCEndpoint"
}
]
}
},
"SgForecVPCEndpoint": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group to allow access to ec2 VPC Endpoint",
"SecurityGroupIngress": [
{
"Description": "vpc endpoint inbound access",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443"
}
],
"SecurityGroupEgress": [
{
"Description": "vpc endpoint outbound access",
"CidrIp": "0.0.0.0/0",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"ecVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"VpcEndpointType": "Interface",
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".ec2"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"SubnetIds": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"PrivateDnsEnabled": true,
"SecurityGroupIds": [
{
"Ref": "SgForecVPCEndpoint"
}
]
}
},
"SgForecmessagesVPCEndpoint": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group to allow access to ec2messages VPC Endpoint",
"SecurityGroupIngress": [
{
"Description": "vpc endpoint inbound access",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443"
}
],
"SecurityGroupEgress": [
{
"Description": "vpc endpoint outbound access",
"CidrIp": "0.0.0.0/0",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"ecmessagesVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"VpcEndpointType": "Interface",
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".ec2messages"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"SubnetIds": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"PrivateDnsEnabled": true,
"SecurityGroupIds": [
{
"Ref": "SgForecmessagesVPCEndpoint"
}
]
}
},
"sVPCEndpoint": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".s3"
]
]
},
"VpcId": {
"Ref": "VPC"
},
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": [
"*"
],
"Resource": [
"*"
]
}
]
},
"RouteTableIds": [
{ "Ref": "PrivateAppRouteTable"}
]
}
},
"PrivateSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"FIRST"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Private",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"SECOND"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Private2",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateSubnet3": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Fn::FindInMap": [
"AWSRegionAvailabilityZone",
{
"Ref": "AWS::Region"
},
"THIRD"
]
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Private3",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"GatewayToInternet": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"InternetGatewayId": {
"Ref": "InternetGateway"
}
}
},
"PublicRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PublicRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": "GatewayToInternet",
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "InternetGateway"
}
}
},
"PublicSubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet"
},
"RouteTableId": {
"Ref": "PublicRouteTable"
}
}
},
"Public2SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet2"
},
"RouteTableId": {
"Ref": "PublicRouteTable"
}
}
},
"Public3SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet3"
},
"RouteTableId": {
"Ref": "PublicRouteTable"
}
}
},
"PrivateAppRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateAppRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": "GatewayToInternet",
"Properties": {
"RouteTableId": {
"Ref": "PrivateAppRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NAT"
}
}
},
"PrivateAppRouteTable2": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateAppRoute2": {
"Type": "AWS::EC2::Route",
"DependsOn": "GatewayToInternet",
"Properties": {
"RouteTableId": {
"Ref": "PrivateAppRouteTable2"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NAT2"
}
}
},
"PrivateAppRouteTable3": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateAppRoute3": {
"Type": "AWS::EC2::Route",
"DependsOn": "GatewayToInternet",
"Properties": {
"RouteTableId": {
"Ref": "PrivateAppRouteTable3"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NAT3"
}
}
},
"PrivateAppSubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateAppSubnet"
},
"RouteTableId": {
"Ref": "PrivateAppRouteTable"
}
}
},
"PrivateApp2SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateAppSubnet2"
},
"RouteTableId": {
"Ref": "PrivateAppRouteTable2"
}
}
},
"PrivateApp3SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateAppSubnet3"
},
"RouteTableId": {
"Ref": "PrivateAppRouteTable3"
}
}
},
"PrivateRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": "NAT",
"Properties": {
"RouteTableId": {
"Ref": "PrivateRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NAT"
}
}
},
"PrivateRouteTable2": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateRoute2": {
"Type": "AWS::EC2::Route",
"DependsOn": "NAT",
"Properties": {
"RouteTableId": {
"Ref": "PrivateRouteTable2"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NAT2"
}
}
},
"PrivateRouteTable3": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateRoute3": {
"Type": "AWS::EC2::Route",
"DependsOn": "NAT",
"Properties": {
"RouteTableId": {
"Ref": "PrivateRouteTable3"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NAT3"
}
}
},
"PrivateSubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet"
},
"RouteTableId": {
"Ref": "PrivateRouteTable"
}
}
},
"Private2SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet2"
},
"RouteTableId": {
"Ref": "PrivateRouteTable2"
}
}
},
"Private3SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet3"
},
"RouteTableId": {
"Ref": "PrivateRouteTable3"
}
}
},
"PublicNetworkAcl": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PrivateAppNetworkAcl": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PrivateNetworkAcl": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"InboundPostgresqlPrivateNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp",
"CIDR"
]
},
"PortRange": {
"From": "5432",
"To": "5432"
}
}
},
"InboundPostgresqlPrivate2NetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "200",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp2",
"CIDR"
]
},
"PortRange": {
"From": "5432",
"To": "5432"
}
}
},
"InboundPostgresqlPrivate3NetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "300",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp3",
"CIDR"
]
},
"PortRange": {
"From": "5432",
"To": "5432"
}
}
},
"OutboundPostgresqlPrivateNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "400",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp",
"CIDR"
]
},
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"OutboundPostgresqlPrivate2NetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "500",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp2",
"CIDR"
]
},
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"OutboundPostgresqlPrivate3NetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "600",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"PrivateApp3",
"CIDR"
]
},
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"InboundPrivateAppNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
},
"RuleNumber": "700",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"InboundDenyRdpPrivateAppNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
},
"RuleNumber": "70",
"Protocol": "6",
"RuleAction": "deny",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "3389",
"To": "3389"
}
}
},
"OutboundPrivateAppNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
},
"RuleNumber": "800",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "80",
"To": "65535"
}
}
},
"OutboundDenyRdpPrivateAppNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
},
"RuleNumber": "80",
"Protocol": "6",
"RuleAction": "deny",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "3389",
"To": "3389"
}
}
},
"InboundHttpsPortPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "443",
"To": "443"
}
}
},
"InboundHttpNatPortPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "200",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "10.40.0.0/16",
"PortRange": {
"From": "80",
"To": "80"
}
}
},
"InboundEphemeralPortPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "300",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"InboundEphemeralPortDenyRdpPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "30",
"Protocol": "6",
"RuleAction": "deny",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "3389",
"To": "3389"
}
}
},
"OutboundHttpPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "400",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "80",
"To": "80"
}
}
},
"OutboundHttpsPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "500",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "443",
"To": "443"
}
}
},
"OutboundEphemeralPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "600",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"OutboundEphemeralDenyRdpPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "60",
"Protocol": "6",
"RuleAction": "deny",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "3389",
"To": "3389"
}
}
},
"PublicSubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet"
},
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
}
}
},
"Public2SubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet2"
},
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
}
}
},
"Public3SubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet3"
},
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
}
}
},
"PrivateAppSubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateAppSubnet"
},
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
}
}
},
"PrivateApp2SubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateAppSubnet2"
},
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
}
}
},
"PrivateApp3SubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateAppSubnet3"
},
"NetworkAclId": {
"Ref": "PrivateAppNetworkAcl"
}
}
},
"PrivateSubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet"
},
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
}
}
},
"Private2SubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet2"
},
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
}
}
},
"Private3SubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet3"
},
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
}
}
},
"DatabaseSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"DependsOn": [ "WebServerSecurityGroup"],
"Properties": {
"GroupDescription": "Database Access",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [
{
"Description": "Postgres inbound access from server",
"IpProtocol": "tcp",
"FromPort": "5432",
"ToPort": "5432",
"SourceSecurityGroupId": {
"Ref": "WebServerSecurityGroup"
}
}
],
"SecurityGroupEgress": [
{
"Description": "Postgres outbound access to server",
"IpProtocol": "tcp",
"FromPort": "5432",
"ToPort": "5432",
"SourceSecurityGroupId": {
"Ref": "WebServerSecurityGroup"
}
}
]
}
},
"DatabaseParamGroup": {
"Type": "AWS::RDS::DBParameterGroup",
"Properties": {
"Description": "Database Parameter Group + pg_stat_statements",
"Family": "postgres16",
"Parameters": {
"max_prepared_transactions": "400",
"max_parallel_workers_per_gather": "4",
"rds.force_ssl": "1",
"rds.force_admin_logging_level": "notice",
"rds.force_autovacuum_logging_level": "notice",
"rds.log_retention_period": "2400",
"shared_preload_libraries": "pg_stat_statements, pgaudit",
"pgaudit.log": "ddl",
"pg_stat_statements.track": "all",
"pg_stat_statements.max": "10000"
}
}
},
"myDBSubnetGroup": {
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupDescription": "DB Private Subnet",
"SubnetIds": [
{
"Ref": "PrivateSubnet"
},
{
"Ref": "PrivateSubnet2"
},
{
"Ref": "PrivateSubnet3"
}
]
}
},
"RDSInstanceRotationSecret": {
"Type": "AWS::SecretsManager::Secret",
"Properties": {
"Description": "This is the secret for my RDS instance",
"SecretString": {
"Fn::Join": [
"",
[
"{\"username\" : \"",
{
"Ref": "DBUsername"
},
"\",\"password\" : \"",
{
"Ref": "DBPassword"
},
"\"}"
]
]
},
"Tags": [
{
"Key": "SecretGroup",
"Value": "RDS"
}
]
}
},
"SecretRDSInstanceAttachment": {
"Type": "AWS::SecretsManager::SecretTargetAttachment",
"Properties": {
"SecretId": {
"Ref": "RDSInstanceRotationSecret"
},
"TargetId": {
"Ref": "Database"
},
"TargetType": "AWS::RDS::DBInstance"
}
},
"MySecretRotationSchedule": {
"Type": "AWS::SecretsManager::RotationSchedule",
"DependsOn": "SecretRotationLambdaInvokePermission",
"Condition": "useRotationLambda",
"Properties": {
"SecretId": {
"Ref": "RDSInstanceRotationSecret"
},
"RotationLambdaARN": {
"Ref": "RotationLambda"
},
"RotationRules": {
"AutomaticallyAfterDays": 1
}
}
},
"SecretRotationLambdaInvokePermission": {
"Type": "AWS::Lambda::Permission",
"DependsOn": "SecretRDSInstanceAttachment",
"Condition": "useRotationLambda",
"Properties": {
"FunctionName": "MySecretsManagerRotationFunction",
"Action": "lambda:InvokeFunction",
"Principal": "secretsmanager.amazonaws.com"
}
},
"Database": {
"Type": "AWS::RDS::DBInstance",
"DependsOn": [
"PrivateRoute",
"DatabaseSecurityGroup"
],
"Properties": {
"DBName": {
"Fn::If": [
"useDBSnapshot",
{
"Ref": "AWS::NoValue"
},
{
"Ref": "DBName"
}
]
},
"StorageEncrypted": "true",
"KmsKeyId": {
"Fn::If": [
"useDBEncryptionKmsAlias",
{
"Ref": "DBEncryptionKmsAlias"
},
{
"Ref": "AWS::NoValue"
}
]
},
"AllocatedStorage": {
"Ref": "DBAllocatedStorage"
},
"CopyTagsToSnapshot": "true",
"Tags": [
{
"Key": "DomainName",
"Value": {
"Ref": "DomainName"
}
},
{
"Key": "DataClassificationConfidentiality",
"Value": "Proprietary"
},
{
"Key": "DataClassificationIntegrity",
"Value": "Standard"
},
{
"Key": "DataClassificationAvailability",
"Value": "Standard"
}
],
"DBInstanceClass": {
"Ref": "DBClass"
},
"Engine": "postgres",
"EngineVersion": "16.2",
"MultiAZ": "true",
"PubliclyAccessible": "false",
"BackupRetentionPeriod": "7",
"EnablePerformanceInsights": "true",
"EnableCloudwatchLogsExports": [
"postgresql",
"upgrade"
],
"StorageType": "gp3",
"DBInstanceIdentifier": "rotation-instance",
"MasterUsername": {
"Fn::If": [
"useDBSnapshot",
{
"Ref": "AWS::NoValue"
},
{
"Fn::Join": [
"",
[
"{{resolve:secretsmanager:",
{
"Ref": "RDSInstanceRotationSecret"
},
":SecretString:username}}"
]
]
}
]
},
"MasterUserPassword": {
"Fn::If": [
"useDBSnapshot",
{
"Ref": "AWS::NoValue"
},
{
"Fn::Join": [
"",
[
"{{resolve:secretsmanager:",
{
"Ref": "RDSInstanceRotationSecret"
},
":SecretString:password}}"
]
]
}
]
},
"DBSnapshotIdentifier": {
"Fn::If": [
"useDBSnapshot",
{
"Ref": "DBSnapshotName"
},
{
"Ref": "AWS::NoValue"
}
]
},
"DBSubnetGroupName": {
"Ref": "myDBSubnetGroup"
},
"DBParameterGroupName": {
"Ref": "DatabaseParamGroup"
},
"VPCSecurityGroups": [
{
"Fn::GetAtt": [
"DatabaseSecurityGroup",
"GroupId"
]
}
]
}
},
"LogsBucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain",
"Properties": {
"AccessControl": "LogDeliveryWrite",
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
"IgnorePublicAcls": true,
"RestrictPublicBuckets": true
},
"LifecycleConfiguration": {
"Rules": [
{
"Id": "Rule for log prefix",
"Status": "Enabled",
"Transitions": [
{
"TransitionInDays": 30,
"StorageClass": "STANDARD_IA"
},
{
"TransitionInDays": 90,
"StorageClass": "GLACIER"
}
],
"ExpirationInDays": 365
}
]
},
"VersioningConfiguration": {
"Status": "Enabled"
},
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
},
"LoggingConfiguration": {
"LogFilePrefix": "/logs/LogsBucket/"
},
"Tags": [
{
"Key": "DomainName",
"Value": {
"Ref": "DomainName"
}
},
{
"Key": "DataClassificationConfidentiality",
"Value": "Proprietary"
},
{
"Key": "DataClassificationIntegrity",
"Value": "Standard"
},
{
"Key": "DataClassificationAvailability",
"Value": "Standard"
}
]
}
},
"LogsBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {
"Ref": "LogsBucket"
},
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ELBAccessLogsAllowAws",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "LogsBucket"
},
"/*"
]
]
},
"Principal": {
"AWS": [
"156460612806"
]
},
"Action": [
"s3:PutObject"
]
},
{
"Sid": "ELBAccessLogsDenyHttp",
"Effect": "Deny",
"Principal": "*",
"Action": [ "s3:GetObject" ],
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "LogsBucket"
},
"/*"
]
]
},
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
}
},
"NAT": {
"DependsOn": "GatewayToInternet",
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": [
"EIP",
"AllocationId"
]
},
"SubnetId": {
"Ref": "PublicSubnet"
},
"Tags": [
{
"Key": "Network",
"Value": "NAT"
}
]
}
},
"NAT2": {
"DependsOn": "GatewayToInternet",
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": [
"EIP2",
"AllocationId"
]
},
"SubnetId": {
"Ref": "PublicSubnet2"
},
"Tags": [
{
"Key": "Network",
"Value": "NAT"
}
]
}
},
"NAT3": {
"DependsOn": "GatewayToInternet",
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": [
"EIP3",
"AllocationId"
]
},
"SubnetId": {
"Ref": "PublicSubnet3"
},
"Tags": [
{
"Key": "Network",
"Value": "NAT"
}
]
}
},
"EIP": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"EIP2": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"EIP3": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"PublicElasticLoadBalancerV2": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"Subnets": [
{
"Ref": "PublicSubnet"
},
{
"Ref": "PublicSubnet2"
},
{
"Ref": "PublicSubnet3"
}
],
"SecurityGroups": [
{
"Ref": "PublicLoadBalancerSecurityGroup"
}
],
"LoadBalancerAttributes": [
{
"Key": "access_logs.s3.enabled",
"Value": "true"
},
{
"Key": "access_logs.s3.bucket",
"Value": {
"Ref": "LogsBucket"
}
},
{
"Key": "access_logs.s3.prefix",
"Value": "Logs"
},
{
"Key": "idle_timeout.timeout_seconds",
"Value": "60"
},
{
"Key": "routing.http.drop_invalid_header_fields.enabled",
"Value": "true"
},
{
"Key": "routing.http.desync_mitigation_mode",
"Value": "strictest"
}
]
},
"DependsOn": "LogsBucketPolicy"
},
"ResourceGroup": {
"Type": "AWS::ResourceGroups::Group",
"Properties": {
"Name": { "Ref": "DomainName" }
}
},
"AppRgistry" : {
"Type" : "AWS::ServiceCatalogAppRegistry::Application",
"DependsOn" : "WebServerFleet",
"Properties" : {
"Description" : { "Ref": "DomainName" },
"Name" : { "Ref": "DomainName" }
}
},
"AppRgistryResourceAssociation" : {
"Type" : "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
"Properties" : {
"Application" : { "Ref" : "AppRgistry"},
"Resource" : {"Ref" : "AWS::StackId"},
"ResourceType" : "CFN_STACK"
}
},
"AppPolicy": {
"Type": "AWS::ResilienceHub::ResiliencyPolicy",
"DependsOn" : "WebServerFleet",
"Properties": {
"DataLocationConstraint": "AnyLocation",
"Policy": {
"Software": {
"RpoInSecs": 300,
"RtoInSecs": 14400
},
"Hardware": {
"RpoInSecs": 0,
"RtoInSecs": 120
},
"AZ": {
"RpoInSecs": 0,
"RtoInSecs": 120
}
},
"PolicyDescription": "MissionCritical",
"PolicyName": "MissionCritical",
"Tier": "MissionCritical"
}
},
"Application": {
"Type": "AWS::ResilienceHub::App",
"DependsOn": "AppPolicy",
"Properties": {
"AppAssessmentSchedule": "Daily",
"AppTemplateBody": {
"Fn::Sub": "{\"resources\":[{\"logicalResourceId\":{\"identifier\":\"LogsBucket\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::S3::Bucket\",\"name\":\"s3bucket-logs\"},{\"logicalResourceId\":{\"identifier\":\"NAT\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::EC2::NatGateway\",\"name\":\"natgateway-vpc\"},{\"logicalResourceId\":{\"identifier\":\"NAT2\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::EC2::NatGateway\",\"name\":\"natgateway-vpc2\"},{\"logicalResourceId\":{\"identifier\":\"NAT3\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::EC2::NatGateway\",\"name\":\"natgateway-vpc3\"},{\"logicalResourceId\":{\"identifier\":\"WebServerFleet\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::AutoScaling::AutoScalingGroup\",\"name\":\"autoscalinggroup-fleet\"},{\"logicalResourceId\":{\"identifier\":\"ArtifactBucket\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::S3::Bucket\",\"name\":\"s3bucket-art\"},{\"logicalResourceId\":{\"identifier\":\"Database\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::RDS::DBInstance\",\"name\":\"rdsdbinstance-app\"},{\"logicalResourceId\":{\"identifier\":\"DNSRecordCNAME2PublicElasticLoadBalancerV2\",\"logicalStackName\":\"${AWS::StackName}\",\"resourceGroupName\":null},\"type\":\"AWS::Route53::RecordSet\",\"name\":\"route53recordset-app\"}],\"appComponents\":[{\"name\":\"storage-s3bucket-logs\",\"type\":\"AWS::ResilienceHub::StorageAppComponent\",\"resourceNames\":[\"s3bucket-logs\"]},{\"name\":\"networking-nat\",\"type\":\"AWS::ResilienceHub::NetworkingAppComponent\",\"resourceNames\":[\"natgateway-vpc\",\"natgateway-vpc2\",\"natgateway-vpc3\"]},{\"name\":\"compute-app-fleet\",\"type\":\"AWS::ResilienceHub::ComputeAppComponent\",\"resourceNames\":[\"autoscalinggroup-fleet\"]},{\"name\":\"storage-s3bucket-art\",\"type\":\"AWS::ResilienceHub::StorageAppComponent\",\"resourceNames\":[\"s3bucket-art\"]},{\"name\":\"database-rds\",\"type\":\"AWS::ResilienceHub::DatabaseAppComponent\",\"resourceNames\":[\"rdsdbinstance-app\"]},{\"name\":\"networking-dns\",\"type\":\"AWS::ResilienceHub::NetworkingAppComponent\",\"resourceNames\":[\"route53recordset-app\"]},{\"name\":\"appcommon\",\"type\":\"AWS::ResilienceHub::AppCommonAppComponent\",\"resourceNames\":[]}],\"excludedResources\":{\"logicalResourceIds\":[]},\"version\":2.0}"
},
"Description": "Citizen Intelligence Agency",
"Name": {"Fn::Sub": "CIA"},
"ResiliencyPolicyArn": {
"Ref": "AppPolicy"
},
"ResourceMappings": [
{
"LogicalStackName": {
"Ref": "AWS::StackName"
},
"MappingType": "CfnStack",
"PhysicalResourceId": {
"Identifier": {
"Fn::Sub": "${AWS::StackId}"
},
"Type": "Arn"
}
}
]
}
},
"AppAlarmTopic": {
"Type": "AWS::SNS::Topic",
"DependsOn": "Application",
"Properties": {
"Subscription": [
{
"Endpoint": {"Fn::Sub": "admin@${DomainName}"},
"Protocol": "email"
}
],
"KmsMasterKeyId": "alias/aws/sns"
}
},
"AWSResilienceHubRDSInstanceOverUtilizedCpuAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmActions" : [ {
"Ref" : "AppAlarmTopic"
} ],
"AlarmDescription" : "Alarm by AWS Resilience Hub that reports when database CPU utilization is over 90%",
"AlarmName" : {"Fn::Sub": "AWSResilienceHub-RDSInstanceOverUtilizedCpuAlarm-2020-04-01_CIA_rotation-instance"},
"ComparisonOperator" : "GreaterThanThreshold",
"DatapointsToAlarm" : 3,
"Dimensions" : [ {
"Name" : "DBInstanceIdentifier",
"Value" : "rotation-instance"
} ],
"EvaluationPeriods" : 5,
"MetricName" : "CPUUtilization",
"Namespace" : "AWS/RDS",
"Period" : 60,
"Statistic" : "Maximum",
"Threshold" : 90,
"TreatMissingData" : "missing",
"Unit" : "Percent"
}
},
"AWSResilienceHubRDSInstanceLowMemoryAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmActions" : [ {
"Ref" : "AppAlarmTopic"
} ],
"AlarmDescription" : "Alarm by AWS Resilience Hub that reports when database free memory is under 10MB",
"AlarmName" : {"Fn::Sub": "AWSResilienceHub-RDSInstanceLowMemoryAlarm-2020-04-01_CIA_rotation-instance"},
"ComparisonOperator" : "LessThanOrEqualToThreshold",
"DatapointsToAlarm" : 3,
"Dimensions" : [ {
"Name" : "DBInstanceIdentifier",
"Value" : "rotation-instance"
} ],
"EvaluationPeriods" : 5,
"MetricName" : "FreeableMemory",
"Namespace" : "AWS/RDS",
"Period" : 60,
"Statistic" : "Minimum",
"Threshold" : 10485760,
"TreatMissingData" : "missing"
}
},
"AWSResilienceHubApplicationLoadBalancerElbHttp4xxCountAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmName" : {"Fn::Sub": "AWSResilienceHub-ApplicationLoadBalancerElbHttp4xxCountAlarm-2020-04-01_CIA"},
"AlarmDescription" : "Alerts when the number of HTTP 4XX server error codes, which originate from the Application Load Balancer, is greater than or equal to the specified threshold",
"AlarmActions" : [ {
"Ref" : "AppAlarmTopic"
} ],
"MetricName" : "HTTPCode_ELB_4XX_Count",
"Namespace" : "AWS/ApplicationELB",
"Dimensions" : [ {
"Name" : "LoadBalancer",
"Value" : { "Ref": "PublicElasticLoadBalancerV2"}
} ],
"Period" : 60,
"Statistic" : "Sum",
"Threshold" : 100,
"EvaluationPeriods" : 5,
"DatapointsToAlarm" : 3,
"ComparisonOperator" : "GreaterThanOrEqualToThreshold",
"TreatMissingData" : "notBreaching",
"Unit" : "Count"
}
},
"AWSResilienceHubApplicationLoadBalancerElbHttp5xxCountAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmName" : {"Fn::Sub": "AWSResilienceHub-ApplicationLoadBalancerElbHttp5xxCountAlarm-2020-04-01_CIA"},
"AlarmDescription" : "Alerts when the number of HTTP 5XX server error codes, which originate from the Application Load Balancer, is greater than or equal to the specified threshold",
"AlarmActions" : [ {
"Ref" : "AppAlarmTopic"
} ],
"MetricName" : "HTTPCode_ELB_5XX_Count",
"Namespace" : "AWS/ApplicationELB",
"Dimensions" : [ {
"Name" : "LoadBalancer",
"Value" : { "Ref": "PublicElasticLoadBalancerV2"}
} ],
"Period" : 60,
"Statistic" : "Sum",
"Threshold" : 100,
"EvaluationPeriods" : 5,
"DatapointsToAlarm" : 3,
"ComparisonOperator" : "GreaterThanOrEqualToThreshold",
"TreatMissingData" : "notBreaching",
"Unit" : "Count"
}
},
"AWSResilienceHubAsgAbnormalRequestPerTargetAlarmCIAHttpsAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmActions" : [ {
"Ref" : "AppAlarmTopic"
} ],
"AlarmDescription" : "Alarm by AWS Resilience Hub that reports when target group request count is anomalous with band width 1",
"AlarmName" : {"Fn::Sub": "AWSResilienceHub-AsgAbnormalRequestPerTargetAlarm-2020-07-13_CIA-Https"},
"ComparisonOperator" : "GreaterThanUpperThreshold",
"EvaluationPeriods" : 15,
"DatapointsToAlarm" : 10,
"Metrics" : [ {
"Expression" : "ANOMALY_DETECTION_BAND(m1,1)",
"Id" : "ad1"
}, {
"Id" : "m1",
"MetricStat" : {
"Metric" : {
"MetricName" : "RequestCountPerTarget",
"Namespace" : "AWS/ApplicationELB",
"Dimensions" : [ {
"Name" : "TargetGroup",
"Value" : { "Ref": "TargetGroupHttps"}
} ]
},
"Period" : 60,
"Stat" : "Average"
}
} ],
"ThresholdMetricId" : "ad1",
"TreatMissingData" : "missing"
}
},
"AWSResilienceHubAsgManyDyingHostsAlarmrWebServerFleetAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmActions" : [ {
"Ref" : "AppAlarmTopic"
} ],
"AlarmDescription" : "Alarm by AWS Resilience Hub that reports when over time an ASG has many unhealthy hosts",
"AlarmName" : {"Fn::Sub": "AWSResilienceHub-AsgManyDyingHostsAlarm-2020-07-13_CIA_WebServerFleet"},
"ComparisonOperator" : "GreaterThanThreshold",
"EvaluationPeriods" : 180,
"DatapointsToAlarm" : 5,
"Dimensions" : [ {
"Name" : "TargetGroup",
"Value" : { "Ref": "TargetGroupHttps"}
}, {
"Name" : "LoadBalancer",
"Value" : { "Ref": "PublicElasticLoadBalancerV2"}
} ],
"MetricName" : "UnHealthyHostCount",
"Namespace" : "AWS/ApplicationELB",
"Period" : 60,
"Statistic" : "Maximum",
"Threshold" : 1,
"TreatMissingData" : "missing"
}
},
"WebACLAssociation": {
"Type": "AWS::WAFv2::WebACLAssociation",
"DependsOn": "BasicSecurityACL",
"Properties": {
"ResourceArn": {
"Ref": "PublicElasticLoadBalancerV2"
},
"WebACLArn": {
"Fn::GetAtt": [
"BasicSecurityACL",
"Arn"
]
}
}
},
"BasicSecurityACL": {
"Type": "AWS::WAFv2::WebACL",
"DependsOn": "PublicElasticLoadBalancerV2",
"Properties": {
"Name": "BasicSecurityACL",
"Scope": "REGIONAL",
"Description": "This is a BasicSecurityACL",
"DefaultAction": {
"Allow": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "BasicSecurityACLMetric"
},
"Rules": [
{
"Name": "RuleWithAWSManagedRulesAmazonIpReputationList",
"Priority": 0,
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RuleWithAWSManagedRulesAmazonIpReputationList"
},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesAmazonIpReputationList",
"ExcludedRules": []
}
}
},
{
"Name": "RuleWithAWSManagedRulesAnonymousIpList",
"Priority": 1,
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RuleWithAWSManagedRulesAnonymousIpList"
},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesAnonymousIpList",
"ExcludedRules": []
}
}
},
{
"Name": "RuleWithAWSManagedRulesCommonRuleSet",
"Priority": 2,
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RuleWithAWSManagedRulesCommonRuleSet"
},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet",
"ExcludedRules": [
"GenericLFI_BODY",
"GenericRFI_BODY"
]
}
}
},
{
"Name": "RuleWithAWSManagedRulesKnownBadInputsRuleSet",
"Priority": 3,
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RuleWithAWSManagedRulesKnownBadInputsRuleSet"
},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesKnownBadInputsRuleSet",
"ExcludedRules": []
}
}
},
{
"Name": "RuleWithAWSManagedRulesLinuxRuleSet",
"Priority": 4,
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RuleWithAWSManagedRulesLinuxRuleSet"
},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesLinuxRuleSet",
"ExcludedRules": []
}
}
},
{
"Name": "RuleWithAWSManagedRulesUnixRuleSet",
"Priority": 5,
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RuleWithAWSManagedRulesUnixRuleSet"
},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesUnixRuleSet",
"ExcludedRules": []
}
}
}
]
}
},
"DNSRecordCNAME2PublicElasticLoadBalancerV2": {
"Type": "AWS::Route53::RecordSet",
"Condition": "useDomainName",
"DependsOn": "PublicElasticLoadBalancerV2",
"Properties": {
"HostedZoneName": {
"Fn::Join": [
"",
[
{
"Ref": "DomainName"
},
"."
]
]
},
"Comment": {
"Fn::Join": [
"",
[
{
"Ref": "DomainNamePrefix"
},
".",
{
"Ref": "DomainName"
},
"."
]
]
},
"Name": {
"Fn::Join": [
"",
[
{
"Ref": "DomainNamePrefix"
},
".",
{
"Ref": "DomainName"
},
"."
]
]
},
"Type": "CNAME",
"TTL": "900",
"ResourceRecords": [
{
"Fn::GetAtt": [
"PublicElasticLoadBalancerV2",
"DNSName"
]
}
]
}
},
"LoadBalancerListenerHttpsCert": {
"Type" : "AWS::CertificateManager::Certificate",
"Properties" : {
"CertificateTransparencyLoggingPreference" : "ENABLED",
"DomainName" : {
"Fn::Join": [
"",
[
{
"Ref": "DomainNamePrefix"
},
".",
{
"Ref": "DomainName"
},
""
]
]
},
"ValidationMethod" : "DNS"
}
},
"LoadBalancerListenerHttpsV2": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"DefaultActions": [
{
"Type": "forward",
"TargetGroupArn": {
"Ref": "TargetGroupHttps"
}
}
],
"LoadBalancerArn": {
"Ref": "PublicElasticLoadBalancerV2"
},
"Certificates": [
{
"CertificateArn": {
"Ref": "LoadBalancerListenerHttpsCert"
}
}
],
"Port": 443,
"Protocol": "HTTPS",
"SslPolicy": "ELBSecurityPolicy-FS-1-2-Res-2019-08"
}
},
"TargetGroupHttps": {
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"Name": "CIA-Https",
"Port": 8443,
"Protocol": "HTTPS",
"VpcId": {
"Ref": "VPC"
},
"HealthCheckPort": 8443,
"HealthCheckIntervalSeconds": 5,
"HealthCheckProtocol": "HTTPS",
"HealthCheckPath": "/healthcheck/",
"HealthCheckTimeoutSeconds": 4,
"HealthyThresholdCount": 2,
"UnhealthyThresholdCount": 6,
"Matcher": {
"HttpCode": "200"
},
"TargetGroupAttributes": [
{
"Key": "stickiness.enabled",
"Value": "true"
},
{
"Key": "stickiness.type",
"Value": "lb_cookie"
},
{
"Key": "stickiness.lb_cookie.duration_seconds",
"Value": "180"
}
]
},
"DependsOn": [
"PublicElasticLoadBalancerV2"
]
},
"PublicLoadBalancerSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Public ELB Security Group with HTTPS access on port 443 from the internet",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [
{
"Description" : "Inbound https from public",
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"Description" : "Outbound https from loadbalancer to server",
"IpProtocol": "tcp",
"FromPort": "8443",
"ToPort": "8443",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
}
}
]
}
},
"WebServerFleet": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"DependsOn": [
"PublicRoute",
"Database"
],
"Properties": {
"AvailabilityZones": [
{
"Fn::GetAtt": [
"PrivateAppSubnet",
"AvailabilityZone"
]
},
{
"Fn::GetAtt": [
"PrivateAppSubnet2",
"AvailabilityZone"
]
},
{
"Fn::GetAtt": [
"PrivateAppSubnet3",
"AvailabilityZone"
]
}
],
"VPCZoneIdentifier": [
{
"Ref": "PrivateAppSubnet"
},
{
"Ref": "PrivateAppSubnet2"
},
{
"Ref": "PrivateAppSubnet3"
}
],
"LaunchConfigurationName": {
"Ref": "WebServerLaunchConfig"
},
"MinSize": "2",
"MaxSize": "3",
"DesiredCapacity": {
"Ref": "WebServerCount"
},
"TargetGroupARNs": [
{
"Ref": "TargetGroupHttps"
}
],
"Tags": [
{
"Key": "Network",
"Value": "Public",
"PropagateAtLaunch": "true"
},
{
"Key": "SecurityBaselineCheck",
"Value": "true",
"PropagateAtLaunch": "true"
},
{
"Key": "UpdateSSMAgent",
"Value": "true",
"PropagateAtLaunch": "true"
},
{
"Key": "GatherSoftwareInventory",
"Value": "true",
"PropagateAtLaunch": "true"
},
{
"Key": "SystemPatchComplianceMaintenanceWindowActive",
"Value": "true",
"PropagateAtLaunch": "true"
}
]
},
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT45M",
"Count": {
"Ref": "WebServerCount"
}
}
},
"UpdatePolicy": {
"AutoScalingRollingUpdate": {
"MinInstancesInService": "1",
"MaxBatchSize": "1",
"PauseTime": "PT15M",
"WaitOnResourceSignals": "true"
}
}
},
"WebServerScaleUpPolicy": {
"Type": "AWS::AutoScaling::ScalingPolicy",
"Properties": {
"AdjustmentType": "ChangeInCapacity",
"AutoScalingGroupName": {
"Ref": "WebServerFleet"
},
"Cooldown": "60",
"ScalingAdjustment": "1"
}
},
"WebServerScaleDownPolicy": {
"Type": "AWS::AutoScaling::ScalingPolicy",
"Properties": {
"AdjustmentType": "ChangeInCapacity",
"AutoScalingGroupName": {
"Ref": "WebServerFleet"
},
"Cooldown": "60",
"ScalingAdjustment": "-1"
}
},
"CPUAlarmHigh": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Scale-up if CPU > 60% for 30 minutes",
"MetricName": "CPUUtilization",
"Namespace": "AWS/EC2",
"Statistic": "Average",
"Period": "900",
"EvaluationPeriods": "2",
"Threshold": "60",
"AlarmActions": [
{
"Ref": "WebServerScaleUpPolicy"
}
],
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": {
"Ref": "WebServerFleet"
}
}
],
"ComparisonOperator": "GreaterThanThreshold"
}
},
"CPUAlarmLow": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Scale-down if CPU < 40% for 30 minutes",
"MetricName": "CPUUtilization",
"Namespace": "AWS/EC2",
"Statistic": "Average",
"Period": "900",
"EvaluationPeriods": "2",
"Threshold": "40",
"AlarmActions": [
{
"Ref": "WebServerScaleDownPolicy"
}
],
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": {
"Ref": "WebServerFleet"
}
}
],
"ComparisonOperator": "LessThanThreshold"
}
},
"InstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Roles": [
{
"Ref": "EC2SSMRole"
}
],
"InstanceProfileName": "EC2SSMInstanceProfile"
}
},
"EC2SSMRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
],
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Policies": [
{
"PolicyName": "rdssecretaccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:DescribeSecret",
"secretsmanager:GetSecretValue"
],
"Resource": {
"Ref": "RDSInstanceRotationSecret"
}
}
]
}
},
{
"PolicyName": "limitedssm",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:PutInventory",
"ssm:PutComplianceItems",
"ssm:PutConfigurePackageResult",
"ssm:UpdateAssociationStatus",
"ssm:UpdateInstanceAssociationStatus",
"ssm:UpdateInstanceInformation",
"ssm:ListAssociations",
"ssm:DescribeAssociation",
"ssm:ListInstanceAssociations",
"ec2:DescribeInstanceStatus",
"ec2messages:AcknowledgeMessage",
"ec2messages:DeleteMessage",
"ec2messages:FailMessage",
"ec2messages:GetEndpoint",
"ec2messages:GetMessages",
"ec2messages:SendReply",
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
"ssm:CreateAssociation",
"ssm:CreateAssociationBatch",
"ssm:RegisterTargetWithMaintenanceWindow",
"ssm:RegisterTaskWithMaintenanceWindow",
"ssm:StartAutomationExecution",
"ssm:UpdateMaintenanceWindowTarget",
"ssm:UpdateMaintenanceWindowTask",
"cloudwatch:DescribeAlarmHistory",
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricData",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"cloudwatch:PutMetricAlarm",
"cloudwatch:PutMetricData"
],
"Resource": "*"
}
]
}
},
{
"PolicyName": "allowgathersoftware",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:GetDocument",
"Resource": {
"Fn::Sub": "arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-GatherSoftwareInventory"
}
}
]
}
},
{
"PolicyName": "allowrunpatchline",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:GetDocument",
"Resource": {
"Fn::Sub": "arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-RunPatchBaseline"
}
}
]
}
},
{
"PolicyName": "allowupdatessmagent",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:GetDocument",
"Resource": {
"Fn::Sub": "arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-UpdateSSMAgent"
}
}
]
}
}
],
"RoleName": "EC2SSMRole"
}
},
"WebServerLaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Metadata": {
"AWS::CloudFormation::Init": {
"config": {
"packages": {
"apt": {
"openjdk-17-jdk-headless": [],
"ntp": [],
"ntpdate": [],
"ufw": [],
"unzip": [],
"language-pack-en": [],
"apt-listchanges": [],
"debian-goodies": [],
"needrestart": [],
"apt-show-versions": [],
"sysstat": [],
"debsecan": [],
"debsums": [],
"fail2ban": []
}
},
"files": {
"/etc/cfn/cfn-hup.conf": {
"content": {
"Fn::Join": [
"",
[
"[main]\n",
"stack=",
{
"Ref": "AWS::StackId"
},
"\n",
"region=",
{
"Ref": "AWS::Region"
},
"\n"
]
]
},
"mode": "000400",
"owner": "root",
"group": "root"
},
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
"content": {
"Fn::Join": [
"",
[
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.WebServerLaunchConfig.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -v ",
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource WebServerLaunchConfig ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n",
"runas=root\n"
]
]
}
},
"/lib/systemd/system/cfn-hup.service": {
"content": {
"Fn::Join": [
"",
[
"[Unit]\n",
"Description=cfn-hup daemon\n\n",
"[Service]\n",
"Type=simple\n",
"ExecStart=/opt/aws/bin/cfn-hup\n",
"Restart=always\n\n",
"[Install]\n",
"WantedBy=multi-user.target"
]
]
}
},
"/etc/awslogs.conf": {
"content": {
"Fn::Join": [
"",
[
"[general]",
"\n",
"state_file = /var/awslogs/state/agent-state",
"\n",
"\n",
"[userdata]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /var/log/user-data.log",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-userdata",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n",
"\n",
"[auth]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /var/log/auth.log",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-auth",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n",
"\n",
"[syslog]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /var/log/syslog",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-syslog",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n",
"\n",
"[kern.log]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /var/log/kern.log",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-kern.log",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n",
"[rkhunter.log]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /var/log/rkhunter.log",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-rkhunter.log",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n",
"[lynis.log]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /var/log/lynis.log",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-lynis.log",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n",
"[ciaapp.log]",
"\n",
"datetime_format = %Y-%m-%d %H:%M:%S",
"\n",
"file = /opt/cia/cia-base/logs/*.log",
"\n",
"buffer_duration = 5000",
"\n",
"log_stream_name = {instance_id}-{hostname}-{ip_address}-ciaapp.log",
"\n",
"initial_position = start_of_file",
"\n",
"log_group_name = ec2awslogs",
"\n"
]
]
},
"mode": "000644",
"owner": "root",
"group": "root"
}
},
"services": {}
}
}
},
"Properties": {
"ImageId": {
"Ref": "WebServerAmi"
},
"MetadataOptions": {
"HttpEndpoint": "enabled",
"HttpPutResponseHopLimit": 1,
"HttpTokens": "required"
},
"IamInstanceProfile": {
"Ref": "InstanceProfile"
},
"EbsOptimized": "true",
"SecurityGroups": [
{
"Ref": "WebServerSecurityGroup"
}
],
"InstanceType": {
"Ref": "WebServerInstanceType"
},
"AssociatePublicIpAddress": "false",
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash -xe\n",
"exec > >(tee /var/log/user-data.log) 2>&1 \n",
"export DEBIAN_FRONTEND=noninteractive\n",
"apt_get_install()\n",
"{\n",
"DEBIAN_FRONTEND=noninteractive apt-get -y \\n",
"-o DPkg::Options::=--force-confnew \\n",
"install $@\n",
"}\n",
"timedatectl set-timezone Europe/Stockholm \n",
"dpkg-reconfigure -f noninteractive tzdata \n",
"echo 'LANG=\"en_US.UTF-8\"'> /etc/default/locale\n",
"locale-gen en_US.UTF-8 en_GB.UTF-8 sv_SE.UTF-8 \n",
"dpkg-reconfigure --frontend=noninteractive locales \n",
"apt-get update\n",
"apt-get -y install apt-transport-https\n",
"apt-get update\n",
"apt-get -y dist-upgrade\n",
"apt-get -y install python3-pip python3-setuptools unattended-upgrades chrony\n",
"echo 'server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4' >> /etc/chrony/chrony.conf \n",
"sudo /etc/init.d/chrony restart\n",
"sudo pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n",
"mkdir -p /opt/aws/bin\n",
"sudo ln -s /usr/local/bin/cfn* /opt/aws/bin\n",
"##systemctl enable cfn-hup.service \n",
"##systemctl start cfn-hup.service \n",
"# Install the sample application\n",
"/opt/aws/bin/cfn-init -v ",
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource WebServerLaunchConfig ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n",
"ufw default allow outgoing\n",
"ufw default deny incoming\n",
"sudo /etc/init.d/ssh stop\n",
"sudo apt-get -y purge openssh-server\n",
"ufw allow 8443/tcp\n",
"ufw allow 53\n",
"ufw allow 123/udp\n",
"ufw enable\n",
"#ufw disable\n",
"ufw status verbose\n",
"echo 'Sysctl hardening'\n",
"echo 'kernel.core_uses_pid = 1' >> /etc/sysctl.conf \n",
"echo 'kernel.sysrq = 0' >> /etc/sysctl.conf \n",
"echo 'kernel.kptr_restrict = 2' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.all.rp_filter = 1' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.default = 1' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.all.accept_redirects = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.default.accept_redirects = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.all.accept_redirects = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.all.log_martians = 1' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.default.log_martians = 1' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.all.log_martians = 1' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.all.send_redirects = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.conf.default.accept_source_route = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.tcp_syncookies = 1' >> /etc/sysctl.conf \n",
"echo 'net.ipv4.tcp_timestamps = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv6.conf.all.accept_redirects = 0' >> /etc/sysctl.conf \n",
"echo 'net.ipv6.conf.default.accept_redirects = 0' >> /etc/sysctl.conf \n",
"sysctl -p\n",
"cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local\n",
"sudo snap install amazon-ssm-agent --classic\n",
"sudo systemctl start snap.amazon-ssm-agent.amazon-ssm-agent.service\n",
"sudo apt-get -y install curl python3 python2 software-properties-common xz-utils bzip2 gnupg wget graphviz\n",
"sudo ln -s /usr/bin/python2 /usr/bin/python\n",
"sudo wget -O /tmp/awslogs-agent-setup.py https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py\n",
"sudo chmod 775 /tmp/awslogs-agent-setup.py\n",
"sudo mkdir -p /var/awslogs/etc/\n",
"sudo /tmp/awslogs-agent-setup.py -n -r eu-west-1 -c /etc/awslogs.conf\n",
"sudo apt-get -y install libwww-perl libdatetime-perl\n",
"# INSTALL OPEN JDK\n",
"sudo ln -s /usr/lib/jvm/java-17-openjdk-arm64 /usr/lib/jvm/jdk-17\n",
"wget -O amazon-corretto-21-aarch64-linux-jdk.deb https://corretto.aws/downloads/latest/amazon-corretto-21-aarch64-linux-jdk.deb\n",
"dpkg -i amazon-corretto-21-aarch64-linux-jdk.deb\n",
"rm amazon-corretto-21-aarch64-linux-jdk.deb\n",
"ln -s /usr/lib/jvm/java-21-amazon-corretto /usr/lib/jvm/jdk-21\n",
"wget ",
{
"Ref": "DebPackageUrl"
},
" -O cia-dist-deb.deb \n",
"dpkg -i --force all cia-dist-deb.deb \n",
"/etc/init.d/cia stop\n",
"echo 'database.name=",
{
"Ref": "DBName"
},
"' >> /opt/cia/cia-base/webapps/cia/WEB-INF/database.properties\n",
"echo 'database.username=allhaildiscordia",
"' >> /opt/cia/cia-base/webapps/cia/WEB-INF/database.properties\n",
"echo 'database.password=legalizeit",
"' >> /opt/cia/cia-base/webapps/cia/WEB-INF/database.properties\n",
"echo 'database.aws.secret.arn=",
{
"Ref": "RDSInstanceRotationSecret"
},
"' >> /opt/cia/cia-base/webapps/cia/WEB-INF/database.properties\n",
"echo 'database.aws.secret=true",
"' >> /opt/cia/cia-base/webapps/cia/WEB-INF/database.properties\n",
"echo 'database.hostname=",
{
"Fn::GetAtt": [
"Database",
"Endpoint.Address"
]
},
"' >> /opt/cia/cia-base/webapps/cia/WEB-INF/database.properties\n",
"sed -i -e 's_\">/cia<_\">/<_' /opt/cia/cia-base/webapps/cia.xml\n",
"TOKEN=$(curl -X PUT 'http://169.254.169.254/latest/api/token' -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600')\n",
"LOCAL_IP=$(curl -H 'X-aws-ec2-metadata-token: $TOKEN' http://169.254.169.254/latest/meta-data/local-ipv4)\n",
"HISTCONTROL=ignorespace\n",
"KEY_PWD=$(< /dev/urandom tr -dc A-Z-a-z-0-9 | head -c${1:-32};echo)\n",
"rm -rf /opt/cia/cia-base/etc/keystore.p12\n",
"/usr/lib/jvm/jdk-17/bin/keytool -genkey -noprompt -deststoretype pkcs12 -sigalg SHA256withRSA -validity 365 -keyalg RSA -keysize 4096 ",
" -alias jetty -dname 'CN=$LOCAL_IP, OU=None, O=None, L=None, S=None, C=SE' -keystore /opt/cia/cia-base/etc/keystore.p12 ",
" -storepass $KEY_PWD -keypass $KEY_PWD\n",
"chown cia:cia /opt/cia/cia-base/etc/keystore.p12\n",
"chmod 700 /opt/cia/cia-base/etc/keystore.p12\n",
" sed -i -e 's_jetty.sslContext.keyManagerPassword=changeit_jetty.sslContext.keyManagerPassword='$KEY_PWD'_' /opt/cia/cia-base/start.d/ssl.ini\n",
" sed -i -e 's_jetty.sslContext.keyStorePassword=changeit_jetty.sslContext.keyStorePassword='$KEY_PWD'_' /opt/cia/cia-base/start.d/ssl.ini\n",
"TOTAL_MEM_KB=$(awk '/MemTotal:/ { print $2 }' /proc/meminfo)\n",
"let JAVAMEMSIZE=$TOTAL_MEM_KB-3046*1024\n",
"sed -i -e 's_4096m_'$JAVAMEMSIZE'k_' /etc/default/cia\n",
"# sed -i -e 's/# -DUSE_LOG_APPENDER=",
{
"Ref": "WebServerAppLogAppender"
},
"/ -DUSE_LOG_APPENDER=",
{
"Ref": "WebServerAppLogAppender"
},
"/' /etc/default/cia\n",
"wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem\n",
"mkdir /opt/cia/.postgresql\n",
"cp rds-combined-ca-bundle.pem /opt/cia/.postgresql/root.crt\n",
"chown -R cia:cia /opt/cia/.postgresql\n",
"chmod -R 700 /opt/cia/.postgresql\n",
"/usr/lib/jvm/jdk-17/bin/keytool -import -keystore /etc/ssl/certs/java/cacerts -file rds-combined-ca-bundle.pem -storepass 'changeit' -noprompt -alias aws-rds-2016\n",
"/etc/init.d/cia stop\n",
"/etc/init.d/cia start\n",
"update-rc.d cia defaults\n",
"# Signal completion\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ",
{
"Ref": "AWS::StackId"
},
" --resource WebServerFleet ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n"
]
]
}
}
}
},
"WebServerSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"DependsOn": "PublicLoadBalancerSecurityGroup",
"Properties": {
"GroupDescription": "Allow access from load balancer and bastion as well as outbound HTTP and HTTPS traffic",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [
{
"Description": "Loadbalancer inbound access",
"IpProtocol": "tcp",
"FromPort": "8443",
"ToPort": "8443",
"SourceSecurityGroupId": {
"Ref": "PublicLoadBalancerSecurityGroup"
}
}
],
"SecurityGroupEgress": [
{
"Description": "Loadbalancer outbound access",
"IpProtocol": "tcp",
"FromPort": "8443",
"ToPort": "8443",
"SourceSecurityGroupId": {
"Ref": "PublicLoadBalancerSecurityGroup"
}
},
{
"Description": "Server outbound http access",
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"Description": "Server outbound https access",
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"Description": "Server outbound postgres access",
"IpProtocol": "tcp",
"FromPort": "5432",
"ToPort": "5432",
"CidrIp": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
}
},
{
"Description": "Server outbound ntp access",
"IpProtocol": "udp",
"FromPort": "123",
"ToPort": "123",
"CidrIp": "0.0.0.0/0"
},
{
"Description": "Server outbound udp dns access",
"IpProtocol": "udp",
"FromPort": "53",
"ToPort": "53",
"CidrIp": "0.0.0.0/0"
},
{
"Description": "Server outbound tcp dns access",
"IpProtocol": "tcp",
"FromPort": "53",
"ToPort": "53",
"CidrIp": "0.0.0.0/0"
}
]
}
}
},
"Outputs": {
"WebSite": {
"Description": "URL of the website",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Fn::GetAtt": [
"PublicElasticLoadBalancerV2",
"DNSName"
]
}
]
]
}
},
"JDBCConnectionString": {
"Description": "JDBC connection string for database",
"Value": {
"Fn::Join": [
"",
[
"jdbc:postgresql://",
{
"Fn::GetAtt": [
"Database",
"Endpoint.Address"
]
},
":",
{
"Fn::GetAtt": [
"Database",
"Endpoint.Port"
]
},
"/",
{
"Ref": "DBName"
}
]
]
}
}
}
}