diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..c1f575e --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +vault_password_file=open_the_vault.sh diff --git a/open_the_vault.sh b/open_the_vault.sh new file mode 100755 index 0000000..469ceef --- /dev/null +++ b/open_the_vault.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +gpg --batch --use-agent --decrypt vault_passphrase.gpg + +exit 0 diff --git a/playbooks/base.yml b/playbooks/base.yml index a016e39..a36c877 100644 --- a/playbooks/base.yml +++ b/playbooks/base.yml @@ -20,4 +20,3 @@ InstanceType: "t2.micro" KeyName: "{{ keys }}" DeployRepo: "{{ deployrepo }}" - AvailabilityZone: "{{ availability_zone }}" diff --git a/playbooks/rds.yml b/playbooks/rds.yml new file mode 100644 index 0000000..133548f --- /dev/null +++ b/playbooks/rds.yml @@ -0,0 +1,21 @@ +--- +- hosts: localhost + connection: local + gather_facts: False + + vars_files: + - "../vars/default.yml" + - "../vars/sec.yml" + + tasks: + - name: Configure MIG RDS + action: cloudformation + stack_name="{{ rds_stack_name }}" + state="{{ state }}" + region="{{ region }}" + template="../templates/rds.json" + args: + template_parameters: + Environment: "{{ env }}" + DBPassword: "{{ migdbpass }}" + BaseStack: "{{ base_stack_name }}" diff --git a/templates/base.json b/templates/base.json index 1359792..ab45fa8 100644 --- a/templates/base.json +++ b/templates/base.json @@ -27,10 +27,6 @@ "DeployRepo": { "Type": "String", "Description": "URL for MIG deploy repo" - }, - "AvailabilityZone": { - "Type": "String", - "Description": "Availability zone to use for subnets" } }, "Resources": { @@ -58,14 +54,25 @@ "InternetGatewayId": { "Ref": "InternetGateway" } } }, - "PublicSubnet": { + "PublicSubnet1": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "CidrBlock": "10.20.0.0/24", - "AvailabilityZone": { "Ref": "AvailabilityZone" }, + "AvailabilityZone": { "Fn::Select": ["0", { "Fn::GetAZs": "" }] }, "Tags": [ - { "Key": "Name", "Value": "mig public subnet" } + { "Key": "Name", "Value": "mig public subnet 1" } + ] + } + }, + "PublicSubnet2": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { "Ref": "VPC" }, + "CidrBlock": "10.20.1.0/24", + "AvailabilityZone": { "Fn::Select": ["1", { "Fn::GetAZs": "" }] }, + "Tags": [ + { "Key": "Name", "Value": "mig public subnet 2" } ] } }, @@ -87,22 +94,41 @@ "GatewayId": { "Ref": "InternetGateway" } } }, - "PublicRouteTableAssoc": { + "PublicRouteTableAssoc1": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { - "SubnetId": { "Ref": "PublicSubnet" }, + "SubnetId": { "Ref": "PublicSubnet1" }, "RouteTableId": { "Ref": "PublicRouteTable" } } }, - "PrivateSubnet": { + "PublicRouteTableAssoc2": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { "Ref": "PublicSubnet2" }, + "RouteTableId": { "Ref": "PublicRouteTable" } + } + }, + "PrivateSubnet1": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, - "CidrBlock": "10.20.1.0/24", - "AvailabilityZone": { "Ref": "AvailabilityZone" }, + "CidrBlock": "10.20.2.0/24", + "AvailabilityZone": { "Fn::Select": ["0", { "Fn::GetAZs": "" }] }, "MapPublicIpOnLaunch": "false", "Tags": [ - { "Key": "Name", "Value": "mig private subnet" } + { "Key": "Name", "Value": "mig private subnet 1" } + ] + } + }, + "PrivateSubnet2": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { "Ref": "VPC" }, + "CidrBlock": "10.20.3.0/24", + "AvailabilityZone": { "Fn::Select": ["1", { "Fn::GetAZs": "" }] }, + "MapPublicIpOnLaunch": "false", + "Tags": [ + { "Key": "Name", "Value": "mig private subnet 2" } ] } }, @@ -124,10 +150,17 @@ "InstanceId": { "Ref": "BastionInstance" } } }, - "PrivateRouteTableAssoc": { + "PrivateRouteTableAssoc1": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { - "SubnetId": { "Ref": "PrivateSubnet" }, + "SubnetId": { "Ref": "PrivateSubnet1" }, + "RouteTableId": { "Ref": "PrivateRouteTable" } + } + }, + "PrivateRouteTableAssoc2": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { "Ref": "PrivateSubnet2" }, "RouteTableId": { "Ref": "PrivateRouteTable" } } }, @@ -144,7 +177,7 @@ "AssociatePublicIpAddress": "true", "DeviceIndex": "0", "DeleteOnTermination": "true", - "SubnetId": { "Ref": "PublicSubnet" } + "SubnetId": { "Ref": "PublicSubnet1" } }], "Tags": [ { "Key": "Name", "Value": "mig bastion host" } @@ -174,7 +207,7 @@ "VpcId": { "Ref": "VPC" }, "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0" }, - { "IpProtocol": "tcp", "FromPort": "0", "ToPort": "65535", "CidrIp": "10.20.0.0/16" }, + { "IpProtocol": "tcp", "FromPort": "0", "ToPort": "65535", "CidrIp": "10.20.0.0/16" } ], "Tags": [ { "Key": "Name", "Value": "mig bastion security group" } @@ -188,20 +221,25 @@ "Value": { "Ref": "VPC" }, "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-VPCId" }} }, - "PrivateSubnet": { - "Description": "Private subnet ID", - "Value": { "Ref": "PrivateSubnet" }, - "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-PrivateSubnet" }} + "PrivateSubnet1": { + "Description": "Private subnet 1 ID", + "Value": { "Ref": "PrivateSubnet1" }, + "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-PrivateSubnet1" }} }, - "PublicSubnet": { - "Description": "Public subnet ID", - "Value": { "Ref": "PublicSubnet" }, - "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-PublicSubnet" }} + "PrivateSubnet2": { + "Description": "Private subnet 2 ID", + "Value": { "Ref": "PrivateSubnet2" }, + "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-PrivateSubnet2" }} }, - "AvailabilityZone": { - "Description": "Availability zone", - "Value": { "Ref": "AvailabilityZone" }, - "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-AvailabilityZone" }} + "PublicSubnet1": { + "Description": "Public subnet 1 ID", + "Value": { "Ref": "PublicSubnet1" }, + "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-PublicSubnet1" }} + }, + "PublicSubnet2": { + "Description": "Public subnet 2 ID", + "Value": { "Ref": "PublicSubnet2" }, + "Export": { "Name": {"Fn::Sub": "${AWS::StackName}-PublicSubnet2" }} }, "BastionInstanceId": { "Description": "Bastion host instance ID", diff --git a/templates/rds.json b/templates/rds.json new file mode 100644 index 0000000..6f0d8bf --- /dev/null +++ b/templates/rds.json @@ -0,0 +1,82 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "MIG database", + "Parameters": { + "Environment": { + "AllowedValues": [ + "dev", + "stage", + "prod" + ], + "Default": "dev", + "Description": "Environment", + "Type": "String" + }, + "BaseStack": { + "Description": "Name of base stack", + "Type": "String" + }, + "DBAllocatedStorage": { + "Description": "DB storage in GB", + "Type": "String", + "Default": "8" + }, + "DBInstanceClass": { + "Description": "DB instance class", + "Type": "String", + "Default": "db.r3.large" + }, + "DBUser": { + "Description": "DB username", + "Type": "String", + "Default": "migadmin" + }, + "DBPassword": { + "Description": "DB password", + "Type": "String" + } + }, + "Resources": { + "DBSubnetGroup": { + "Type": "AWS::RDS::DBSubnetGroup", + "Properties": { + "DBSubnetGroupDescription": "mig db subnet group", + "SubnetIds": [ + { "Fn::ImportValue": { "Fn::Sub": "${BaseStack}-PrivateSubnet1" }}, + { "Fn::ImportValue": { "Fn::Sub": "${BaseStack}-PrivateSubnet2" }} + ] + } + }, + "DB": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "AllocatedStorage": { "Ref": "DBAllocatedStorage" }, + "BackupRetentionPeriod": "30", + "DBInstanceClass": { "Ref": "DBInstanceClass" }, + "DBInstanceIdentifier": { "Fn::Sub": "db-${AWS::StackName}" }, + "DBName": "mig", + "VPCSecurityGroups": [ { "Ref": "DBSecurityGroup" } ], + "Engine": "postgres", + "EngineVersion": "9.4.7", + "MasterUsername": { "Ref": "DBUser" }, + "MasterUserPassword": { "Ref": "DBPassword" }, + "DBSubnetGroupName": { "Ref": "DBSubnetGroup" }, + "PubliclyAccessible": "false" + } + }, + "DBSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "VpcId": { "Fn::ImportValue": { "Fn::Sub": "${BaseStack}-VPCId" }}, + "GroupDescription": "Security group for MIG RDS instance", + "SecurityGroupIngress": [ + { "IpProtocol": "tcp", "FromPort": "5432", "ToPort": "5432", "CidrIp": "10.20.2.0/24" }, + { "IpProtocol": "tcp", "FromPort": "5432", "ToPort": "5432", "CidrIp": "10.20.3.0/24" } + ], + "Tags": [ + { "Key": "Name", "Value": "mig rds security group" } + ] + } + } + } +} diff --git a/vars/default.yml b/vars/default.yml index 4bc54c9..9a22da0 100644 --- a/vars/default.yml +++ b/vars/default.yml @@ -1,6 +1,7 @@ --- region: us-west-2 availability_zone: us-west-2a +availability_zone2: us-west-2b keys: "alm-keys" ami_id: ami-2709bd47 state: present @@ -13,3 +14,6 @@ base_stack_name: "mig-base-{{ base_stack_id }}" app_stack_id: "1" app_stack_name: "mig-app-{{ app_stack_id }}" api_certificate_name: "migapitmp" + +rds_stack_id: "1" +rds_stack_name: "mig-rds-{{ rds_stack_id }}" diff --git a/vars/sec.yml b/vars/sec.yml new file mode 100644 index 0000000..c91bda2 --- /dev/null +++ b/vars/sec.yml @@ -0,0 +1,8 @@ +$ANSIBLE_VAULT;1.1;AES256 +31333565643430323461353761353031326430636638323435376337353866333561303038393835 +3537363632623234616531323630363538373636316630370a393632636139613138313965633032 +33333161396234303266613634306361373834343965343831396432613862623036303363656266 +6235373761366564660a656138366432343639646131666666656265306236626562656539393962 +33323332646364666264383764623563393738353735326166643232663265626434343238383935 +35393735383761356130636135386438323332393731613838613636386132323838653332326236 +356263633639333764663332373264653563 diff --git a/vault_passphrase.gpg b/vault_passphrase.gpg new file mode 100644 index 0000000..07ce0de --- /dev/null +++ b/vault_passphrase.gpg @@ -0,0 +1,2 @@ + ?X]k2BonΜkEUAG`%ztH]JghR|Vם &ȡj3yCp`/~L,WxOx7h3_Fsi2rߠk,4u-OZv+_z|ñI!K4|2v:|g ۲ND Ae6u!SO-SִIiӰr;ȃ_4)WLBy(kHX"5lik(1f耥OB_@"K?K_grC>ynby[uY5%MmA-ms +LОz)`R}0ڧm/g. '`$WZ aGMF&OӠk g b3(38Vʙ>fv}c xދ /ڭ7Glpe>P0^=p7Q\M:AU0EI3/8=iҰu'^UHvo2ɀ@jh[]P8& \ No newline at end of file