diff --git a/config/settings/production.py b/config/settings/production.py index 4975746..3b37d65 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -9,7 +9,7 @@ SECRET_KEY = env("DJANGO_SECRET_KEY") # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["example.com"]) -REDIS_URL = "redis://" + env("REDIS_HOST", "redis") + ":" + env("REDIS_PORT", "6379") + "/0" +REDIS_URL = "redis://" + env.str("REDIS_HOST", "redis") + ":" + env.str("REDIS_PORT", "6379") + "/0" # DATABASES # ------------------------------------------------------------------------------ diff --git a/rds_redis_backend.yml b/rds_redis_backend.yml new file mode 100644 index 0000000..553e2de --- /dev/null +++ b/rds_redis_backend.yml @@ -0,0 +1,443 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: CloudFormation template for PostgreSQL RDS, Redis ElastiCache, and Ubuntu EC2 instance. + +Parameters: + MyVPC: + Type: AWS::EC2::VPC::Id + Description: The ID of the VPC, eg vpc-0a1234567890abcdef + + AppTagValue: + Type: String + Description: The value of the app tag to apply to resources + Default: myapp + + DBName: + Type: String + Description: The name of the database. Eg, yeastregulatorydb + + PostgresPassword: + Type: String + Description: The master password for the RDS instance. Must be at least 8 characters long. + NoEcho: true + + PostgresUser: + Type: String + Description: The master username for the RDS instance + Default: postgres + + PostgresVersion: + Type: String + Description: The version of Postgres to use for the RDS instance + Default: 15.2 + + PostgresVersionFamily: + Type: String + Description: The version family of Postgres to use for the RDS instance + Default: postgres15 + + RdsInstanceType: + Type: String + Description: The instance type for the RDS instance + Default: db.t3.micro + + RdsAllocatedStorage: + Type: String + Description: The allocated storage for the RDS instance + Default: 20 + + ElasticacheInstanceType: + Type: String + Description: The instance type for the ElastiCache Redis instance + Default: cache.t2.micro + + MyInternetGateway: + Type: String + Description: The ID of the internet gateway, eg igw-0a1234567890abcdef + + SubnetACidrBlock: + Type: String + Default: 172.31.64.0/20 + Description: The CIDR block for Subnet A. + + PrivateSubnetACidrBlock: + Type: String + Default: 172.31.50.0/24 + Description: The CIDR block for Private Subnet A. + + SubnetBCidrBlock: + Type: String + Default: 172.31.80.0/20 + Description: The CIDR block for Subnet B. + + PrivateSubnetBCidrBlock: + Type: String + Default: 172.31.51.0/24 + Description: The CIDR block for Private Subnet B. + + SubnetCCidrBlock: + Type: String + Default: 172.31.96.0/20 + Description: The CIDR block for Subnet C. + + PrivateSubnetCCidrBlock: + Type: String + Default: 172.31.52.0/24 + Description: The CIDR block for Private Subnet C + +Resources: + + SubnetA: + Type: AWS::EC2::Subnet + DependsOn: + - PublicRoute + Properties: + VpcId: !Ref MyVPC + CidrBlock: !Ref SubnetACidrBlock + AvailabilityZone: us-east-2a + Tags: + - Key: app + Value: !Ref AppTagValue + + SubnetB: + Type: AWS::EC2::Subnet + DependsOn: + - PublicRoute + Properties: + VpcId: !Ref MyVPC + CidrBlock: !Ref SubnetBCidrBlock + AvailabilityZone: us-east-2b + Tags: + - Key: app + Value: !Ref AppTagValue + + SubnetC: + Type: AWS::EC2::Subnet + DependsOn: + - PublicRoute + Properties: + VpcId: !Ref MyVPC + CidrBlock: !Ref SubnetCCidrBlock + AvailabilityZone: us-east-2c + Tags: + - Key: app + Value: !Ref AppTagValue + + PrivateSubnetA: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref MyVPC + CidrBlock: !Ref PrivateSubnetACidrBlock + AvailabilityZone: us-east-2a + Tags: + - Key: app + Value: !Ref AppTagValue + + PrivateSubnetB: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref MyVPC + CidrBlock: !Ref PrivateSubnetBCidrBlock + AvailabilityZone: us-east-2b + Tags: + - Key: app + Value: !Ref AppTagValue + + PrivateSubnetC: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref MyVPC + CidrBlock: !Ref PrivateSubnetCCidrBlock + AvailabilityZone: us-east-2c + Tags: + - Key: app + Value: !Ref AppTagValue + + PrivateRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref MyVPC + Tags: + - Key: Name + Value: PrivateRouteTable + + MyPublicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref MyVPC + Tags: + - Key: app + Value: !Ref AppTagValue + + PublicRoute: + Type: AWS::EC2::Route + DependsOn: + - MyPublicRouteTable + Properties: + RouteTableId: !Ref MyPublicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref MyInternetGateway + + SubnetRouteTableAssociationA: + Type: AWS::EC2::SubnetRouteTableAssociation + DependsOn: + - MyPublicRouteTable + - SubnetA + Properties: + SubnetId: !Ref SubnetA + RouteTableId: !Ref MyPublicRouteTable + + SubnetRouteTableAssociationB: + Type: AWS::EC2::SubnetRouteTableAssociation + DependsOn: + - MyPublicRouteTable + - SubnetB + Properties: + SubnetId: !Ref SubnetB + RouteTableId: !Ref MyPublicRouteTable + + SubnetRouteTableAssociationC: + Type: AWS::EC2::SubnetRouteTableAssociation + DependsOn: + - MyPublicRouteTable + - SubnetC + Properties: + SubnetId: !Ref SubnetC + RouteTableId: !Ref MyPublicRouteTable + + AssociationPrivateSubnetA: + Type: AWS::EC2::SubnetRouteTableAssociation + DependsOn: + - PrivateRouteTable + - PrivateSubnetA + Properties: + SubnetId: !Ref PrivateSubnetA + RouteTableId: !Ref PrivateRouteTable + + AssociationPrivateSubnetB: + Type: AWS::EC2::SubnetRouteTableAssociation + DependsOn: + - PrivateRouteTable + - PrivateSubnetB + Properties: + SubnetId: !Ref PrivateSubnetB + RouteTableId: !Ref PrivateRouteTable + + AssociationPrivateSubnetC: + Type: AWS::EC2::SubnetRouteTableAssociation + DependsOn: + - PrivateRouteTable + - PrivateSubnetC + Properties: + SubnetId: !Ref PrivateSubnetC + RouteTableId: !Ref PrivateRouteTable + + DjangoSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security group for Django ECS service allowing HTTP and HTTPS traffic + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: 0.0.0.0/0 + Tags: + - Key: app + Value: !Ref AppTagValue + + RedisSecurityGroup: + Type: AWS::EC2::SecurityGroup + DependsOn: + - DjangoSecurityGroup + Properties: + GroupDescription: Security group for Redis service + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 6379 + ToPort: 6379 + SourceSecurityGroupId: !Ref DjangoSecurityGroup + Tags: + - Key: app + Value: !Ref AppTagValue + + MyDBSecurityGroup: + Type: AWS::EC2::SecurityGroup + DependsOn: + - DjangoSecurityGroup + Properties: + GroupDescription: Allow access to PostgreSQL + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + SourceSecurityGroupId: !Ref DjangoSecurityGroup + Tags: + - Key: app + Value: !Ref AppTagValue + + MyCacheSecurityGroup: + Type: AWS::EC2::SecurityGroup + DependsOn: + - DjangoSecurityGroup + Properties: + GroupDescription: Allow access to Redis + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 6379 + ToPort: 6379 + SourceSecurityGroupId: !Ref DjangoSecurityGroup + Tags: + - Key: app + Value: !Ref AppTagValue + + MyCustomParameterGroup: + Type: AWS::RDS::DBParameterGroup + Properties: + Description: Custom parameter group for my DB + Family: !Ref PostgresVersionFamily + Parameters: + max_connections: "200" + Tags: + - Key: app + Value: !Ref AppTagValue + + MyDBProxyRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: rds.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: RDSProxyPolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + - secretsmanager:DescribeSecret + Resource: '*' + Tags: + - Key: app + Value: !Ref AppTagValue + + MyDBSecret: + Type: AWS::SecretsManager::Secret + DependsOn: MyDBInstance + Properties: + Name: MyDBSecret + Description: RDS database credentials + SecretString: !Sub '{"username": "${PostgresUser}", "password": "${PostgresPassword}"}' + Tags: + - Key: app + Value: !Ref AppTagValue + + MyDBProxy: + Type: AWS::RDS::DBProxy + DependsOn: + - MyDBProxyRole + - MyDBSecret + - MyDBSecurityGroup + Properties: + DBProxyName: mydbproxy + EngineFamily: POSTGRESQL + Auth: + - AuthScheme: SECRETS + IAMAuth: DISABLED + SecretArn: !Ref MyDBSecret + RoleArn: !GetAtt MyDBProxyRole.Arn + VpcSecurityGroupIds: + - !Ref MyDBSecurityGroup + VpcSubnetIds: + - !Ref SubnetA + - !Ref SubnetB + - !Ref SubnetC + RequireTLS: false + Tags: + - Key: app + Value: !Ref AppTagValue + + MyDBSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: "My DB Subnet Group" + SubnetIds: + - !Ref PrivateSubnetA + - !Ref PrivateSubnetB + - !Ref PrivateSubnetC + + MyDBInstance: + Type: AWS::RDS::DBInstance + DependsOn: + - MyDBSubnetGroup + - MyCustomParameterGroup + Properties: + DBName: !Ref DBName + AllocatedStorage: !Ref RdsAllocatedStorage + DBInstanceClass: !Ref RdsInstanceType + Engine: postgres + EngineVersion: !Ref PostgresVersion + MasterUsername: !Ref PostgresUser + MasterUserPassword: !Ref PostgresPassword + BackupRetentionPeriod: 3 + DBSubnetGroupName: !Ref MyDBSubnetGroup + VPCSecurityGroups: + - !Ref MyDBSecurityGroup + DBParameterGroupName: !Ref MyCustomParameterGroup + Tags: + - Key: app + Value: !Ref AppTagValue + + MyElastiCacheSubnetGroup: + Type: AWS::ElastiCache::SubnetGroup + Properties: + Description: "Subnet group for ElastiCache" + SubnetIds: + - !Ref PrivateSubnetA + - !Ref PrivateSubnetB + - !Ref PrivateSubnetC + Tags: + - Key: app + Value: !Ref AppTagValue + + MyElastiCacheRedis: + Type: AWS::ElastiCache::CacheCluster + DependsOn: + - MyCacheSecurityGroup + - RedisSecurityGroup + - MyElastiCacheSubnetGroup + Properties: + CacheNodeType: !Ref ElasticacheInstanceType + Engine: redis + NumCacheNodes: 1 + VpcSecurityGroupIds: + - !Ref MyCacheSecurityGroup + - !Ref RedisSecurityGroup + CacheSubnetGroupName: !Ref MyElastiCacheSubnetGroup + Tags: + - Key: app + Value: !Ref AppTagValue + +Outputs: + RDSProxyEndpoint: + Description: Endpoint of the RDS Proxy + Value: !GetAtt MyDBProxy.Endpoint + + ElastiCacheEndpoint: + Description: Endpoint of the ElastiCache Redis + Value: !GetAtt MyElastiCacheRedis.RedisEndpoint.Address + + ElastiCachePort: + Description: Port of the ElastiCache Redis + Value: !GetAtt MyElastiCacheRedis.RedisEndpoint.Port diff --git a/rds_redis_ec2_config.yml b/rds_redis_ec2_config.yml index a7da85b..29a25bb 100644 --- a/rds_redis_ec2_config.yml +++ b/rds_redis_ec2_config.yml @@ -83,16 +83,16 @@ Resources: VpcSecurityGroupIds: - !Ref MyCacheSecurityGroup - MyEC2Instance: - Type: AWS::EC2::Instance - DependsOn: - - MyInstanceSecurityGroup - Properties: - ImageId: ami-05fb0b8c1424f266b - InstanceType: t2.micro - SecurityGroupIds: - - !GetAtt MyInstanceSecurityGroup.GroupId - KeyName: general_strides + # MyEC2Instance: + # Type: AWS::EC2::Instance + # DependsOn: + # - MyInstanceSecurityGroup + # Properties: + # ImageId: ami-05fb0b8c1424f266b + # InstanceType: t2.micro + # SecurityGroupIds: + # - !GetAtt MyInstanceSecurityGroup.GroupId + # KeyName: general_strides MyDBSecurityGroup: Type: AWS::EC2::SecurityGroup