uits-foundation-deployer.yaml
---

Ansible Admin EC2 CloudFormation Deployment

This CloudFormation template will deploy a single EC2 instance with its own security group. That security group has Admin rights in this account, so be sure to remove this stack as soon as you are finished.

AWSTemplateFormatVersion: '2010-09-09'

Parameters

These are the input parameters for this template. All of these parameters must be supplied for this template to be deployed.

Parameters:

Email Address to be passed into the Ansible scripts for notifications.

AlertEmail: Description: Email Address to send account alerts to Type: String

SSH Key Pair to be used on the application EC2 instances for emergency administrative access.

AccountType: Description: Account Type Type: String Default: Non-Production AllowedValues: - Non-Production - Production - Dry-Run

Branch to pull down and run.

ServiceCatalogBranch: Description: Service Catalog Branch Type: String Default: master

HostName to be used in tagging the EC2 instance.

HostName: Type: String Description: Enter the name of the host or service, ie 'account-foundation-deployer', etc. Default: account-foundation-deployer

SSH Key Pair to be used on the application EC2 instances for emergency administrative access.

KeyName: Description: Amazon EC2 Key Pair Type: AWS::EC2::KeyPair::KeyName

VPCID is the ID of the VPC where this template will be deployed.

VPCID: Description: Target VPC Type: AWS::EC2::VPC::Id InstanceSubnet: Description: Private Subnet Type: AWS::EC2::Subnet::Id ClientIP: Description: Your IP Address Type: String

Zabbix Agent Parameters

ZabbixAPIHostname: Description: The Hostname of the Zabbix Web API Server. Type: String ZabbixProxyHostname: Description: The Hostname of the Zabbix Proxy Host to register with. Type: String ZabbixAPIUsername: Description: Zabbix API Username. Type: String NoEcho: 'true' ZabbixAPIPassword: Description: Zabbix API Password. Type: String NoEcho: 'true'

Tags

The following tags are applied to all resources created by this template.

ServiceTag: Type: String Description: Exact name of the Service as defined in the service catalog. EnvironmentTag: Type: String Description: Used to distinguish between development, test, production,etc. environment types. AllowedValues: [dev, tst, prd, trn, stg, cfg, sup, rpt] Default: dev ContactNetidTag: Type: String Description: Used to identify the netid of the person most familiar with the usage of the resource. AccountNumberTag: Type: String Description: Identifies the financial system account number. TicketNumberTag: Type: String Description: Used to identify the Jira, Cherwell, or other ticketing system ticket number to link to more information about the need for the resource.

Metadata

Metadata is mostly for organizing and presenting Parameters in a better way when using CloudFormation in the AWS Web UI.

Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Account Settings Parameters: - AlertEmail - AccountType - ServiceCatalogBranch - Label: default: Instance Settings Parameters: - HostName - KeyName - VPCID - InstanceSubnet - ClientIP - Label: default: Zabbix Agent Parameters Parameters: - ZabbixAPIHostname - ZabbixProxyHostname - ZabbixAPIUsername - ZabbixAPIPassword - Label: default: Tags Parameters: - ServiceTag - EnvironmentTag - ContactNetidTag - AccountNumberTag - TicketNumberTag ParameterLabels: ServiceTag: default: "Service Name:" EnvironmentTag: default: 'Environment Type:' ContactNetidTag: default: 'Contact NetID:' AccountNumberTag: default: 'Financial Account Number:' TicketNumberTag: default: 'Ticket Number:'

Resources

This is the EC2 instance deployed by the template.

Resources:

EC2 Instance

Deploys the EC2 instance with some tags.

Ec2Instance: Type: AWS::EC2::Instance Metadata: "AWS::CloudFormation::Init": configSets: bootstrap: - initialSetup

Initial Setup

Put config files and service-catalog in place.

initialSetup:

Create the following files on the host

files:

Config files for CloudWatch Logs Agent (awslogs)

/etc/awslogs/awscli.conf: mode: "000644" owner: "root" group: "root" content: !Sub | [plugins] cwlogs = cwlogs [default] region = ${AWS::Region} /etc/awslogs/awslogs.conf: mode: "000644" owner: "root" group: "root" content: !Sub | [general] state_file = /var/lib/awslogs/agent-state [foundation-deployment] file = /tmp/foundation-ansible.log log_group_name = foundation-deployment log_stream_name = {instance_id}-foundation-deployment initial_position = start_of_file /tmp/run-account-setup.sh: mode: "000744" owner: "root" group: "root" content: !Sub | #!/bin/bash -ex cd /home/ec2-user/service-catalog/*/portfolios/account-foundation/ /usr/local/bin/ansible-playbook new-account-playbook.yaml -vvv \ --extra-vars "alarmEmail='${AlertEmail}' \ accountType='${AccountType}' \ ZabbixAPIHostname='${ZabbixAPIHostname}' \ ZabbixProxyHostname='${ZabbixProxyHostname}' \ ZabbixAPIUsername='${ZabbixAPIUsername}' \ ZabbixAPIPassword='${ZabbixAPIPassword}' \ serviceTag='${ServiceTag}' \ environmentTag='${EnvironmentTag}' \ contactNetidTag='${ContactNetidTag}' \ accountNumberTag='${AccountNumberTag}' \ ticketNumberTag='${TicketNumberTag}'" \ >> /tmp/foundation-ansible.log 2>&1

Download and unpack the following archives

sources: /home/ec2-user/service-catalog: !Sub "https://bitbucket.org/ua-ecs/service-catalog/get/${ServiceCatalogBranch}.tar.gz"

A CreationPolicy prevents this resource creation from completing until it receives the signal from cfn-signal.

CreationPolicy: ResourceSignal: Count: 1 Timeout: PT60M Properties: ImageId: ami-7172b611 KeyName: !Ref KeyName InstanceType: t2.micro AvailabilityZone: us-west-2a IamInstanceProfile: !Ref InstanceProfile NetworkInterfaces: - AssociatePublicIpAddress: 'true' DeviceIndex: '0' SubnetId: !Ref InstanceSubnet GroupSet: - !Ref InstanceSecurityGroup UserData: Fn::Base64: !Sub - | #!/bin/bash -xe

Install basic packages

sudo yum update -y sudo yum install -y git telnet vim sudo easy_install pip sudo pip install awscli --upgrade

Install CloudWatch Logs Agnet

sudo yum install -y awslogs

Kick off CloudFormation Init processing

/opt/aws/bin/cfn-init -s ${AWS::StackName} -c bootstrap --region ${AWS::Region} --resource Ec2Instance

Init setsup the config files for awslogs, so start that service now

sudo service awslogs start

Install Amazon SSM

cd /root curl https://amazon-ssm-${AWS::Region}.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o /tmp/amazon-ssm-agent.rpm yum install -y /tmp/amazon-ssm-agent.rpm

Try to install Zabbix Agent

ZabbixParam=$(aws ssm get-parameters --region ${AWS::Region} --names "ZabbixAPIUsername" --with-decryption --query 'Parameters[0].Value' --output text) if [ $ZabbixParam = "__aws_host_remover" ]; then cd /root wget https://s3-us-west-2.amazonaws.com/ua-uits-ecs-public/zabbix/zabbix-agent-install.zip unzip zabbix-agent-install.zip cd zabbix ./install_zabbix_agent.sh "${ZabbixHostname}" "${ZabbixMetadata}" fi

Install Ansible

sudo pip install boto3 cd /root git clone https://github.com/ansible/ansible.git cd ansible sudo make install

Run Foundation Playbook if this isn't a Dry Run.

if [ ${AccountType} != "Dry-Run" ]; then

This shell script is create above in the metadata section of the Ec2Instance

/tmp/run-account-setup.sh fi

Signal CloudFormation with the result of the playbook

/opt/aws/bin/cfn-signal --success --stack ${AWS::StackName} --region ${AWS::Region} --resource Ec2Instance - { ZabbixHostname: !Sub "${HostName}.${AWS::AccountId}.aws", ZabbixMetadata: "aws-server" } Tags: - Key: Name Value: !Ref HostName - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag

Instance Security Group

Security group for the EC2 instance, that allows you to SSH into the instance

InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow ssh to client host VpcId: !Ref VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: !Sub "${ClientIP}/32" Tags: - Key: Name Value: !Sub "${HostName} Security Group" - Key: service Value: !Ref ServiceTag - Key: environment Value: !Ref EnvironmentTag - Key: contactnetid Value: !Ref ContactNetidTag - Key: accountnumber Value: !Ref AccountNumberTag - Key: ticketnumber Value: !Ref TicketNumberTag

Instance Role

This is the IAM role that will be applied to the EC2 Instances. Again this policy is pretty broad, so be careful!

InstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: !Sub "${HostName}-adminPolicy" PolicyDocument: Version: '2012-10-17' Statement: - Sid: Stmt1452033379000 Effect: Allow Action: - "*" Resource: - "*"

Instance Profile

InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - !Ref InstanceRole

Outputs

Output values that can be viewed from the AWS CloudFormation console.

Outputs: InstancePrivateIP: Description: The Private IP address of the instance Value: !GetAtt Ec2Instance.PrivateIp InstancePublicIP: Description: The Public IP address of the instance Value: !GetAtt Ec2Instance.PublicIp InstanceID: Description: The Instance ID Value: !Ref Ec2Instance