This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
AWSTemplateFormatVersion: 2010-09-09 | |
Description: Test Server Infrastructure | |
Parameters: | |
ParentVPCStack: | |
Description: Stack name of parent VPC stack based on vpc/vpc-*azs.yaml template. | |
Type: String | |
Default: 'TestVPC' | |
ParentSSHBastionStack: | |
Description: 'Optional but recommended stack name of parent SSH bastion host/instance stack based on vpc/vpc-ssh-bastion.yaml template.' | |
Type: String | |
Default: 'TestSSHBastion' | |
KeyName: | |
Description: 'Optional key pair of the ec2-user to establish a SSH connection to the EC2 instance.' | |
Type: String | |
Default: '' | |
IAMUserSSHAccess: | |
Description: 'Synchronize public keys of IAM users to enable personalized SSH access (Doc: https://cloudonaut.io/manage-aws-ec2-ssh-access-with-iam/).' | |
Type: String | |
Default: true | |
AllowedValues: | |
- true | |
- false | |
InstanceType: | |
Description: The instance type for the EC2 instance. | |
Type: String | |
Default: t2.micro | |
Name: | |
Description: 'The name for the EC2 instance.' | |
Type: String | |
Default: 'test' | |
Mappings: | |
RegionMap: | |
ap-south-1: | |
AMI: ami-531a4c3c | |
eu-west-3: | |
AMI: ami-8ee056f3 | |
eu-west-2: | |
AMI: ami-403e2524 | |
eu-west-1: | |
AMI: ami-d834aba1 | |
ap-northeast-2: | |
AMI: ami-863090e8 | |
ap-northeast-1: | |
AMI: ami-ceafcba8 | |
sa-east-1: | |
AMI: ami-84175ae8 | |
ca-central-1: | |
AMI: ami-a954d1cd | |
ap-southeast-1: | |
AMI: ami-68097514 | |
ap-southeast-2: | |
AMI: ami-942dd1f6 | |
eu-central-1: | |
AMI: ami-5652ce39 | |
us-east-1: | |
AMI: ami-97785bed | |
us-east-2: | |
AMI: ami-f63b1193 | |
us-west-1: | |
AMI: ami-824c4ee2 | |
us-west-2: | |
AMI: ami-f2d3638a | |
Conditions: | |
HasKeyName: !Not [!Equals [!Ref KeyName, '']] | |
HasIAMUserSSHAccess: !Equals [!Ref IAMUserSSHAccess, 'true'] | |
HasSSHBastionSecurityGroup: !Not [!Equals [!Ref ParentSSHBastionStack, '']] | |
HasNotSSHBastionSecurityGroup: !Equals [!Ref ParentSSHBastionStack, ''] | |
Resources: | |
SecurityGroup: | |
Type: 'AWS::EC2::SecurityGroup' | |
Properties: | |
GroupDescription: !Ref Name | |
VpcId: | |
'Fn::ImportValue': !Sub '${ParentVPCStack}-VPC' | |
SecurityGroupInSSHBastion: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Condition: HasSSHBastionSecurityGroup | |
Properties: | |
GroupId: !Ref SecurityGroup | |
IpProtocol: tcp | |
FromPort: 22 | |
ToPort: 22 | |
SourceSecurityGroupId: | |
'Fn::ImportValue': !Sub '${ParentSSHBastionStack}-SecurityGroup' | |
SecurityGroupInSSHWorld: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Condition: HasNotSSHBastionSecurityGroup | |
Properties: | |
GroupId: !Ref SecurityGroup | |
IpProtocol: tcp | |
FromPort: 22 | |
ToPort: 22 | |
CidrIp: 0.0.0.0/0 | |
SecurityGroupIngressTcp: | |
Type: 'AWS::EC2::SecurityGroupIngress' | |
Properties: | |
GroupId: !Ref SecurityGroup | |
IpProtocol: tcp | |
FromPort: 80 | |
ToPort: 80 | |
CidrIp: 0.0.0.0/0 | |
InstanceProfile: | |
Type: 'AWS::IAM::InstanceProfile' | |
Properties: | |
Path: / | |
Roles: | |
- !Ref IAMRole | |
IAMRole: | |
Type: 'AWS::IAM::Role' | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: | |
- ec2.amazonaws.com | |
Action: | |
- 'sts:AssumeRole' | |
Path: / | |
Policies: | |
- PolicyName: testlogs | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'logs:CreateLogGroup' | |
- 'logs:CreateLogStream' | |
- 'logs:PutLogEvents' | |
- 'logs:DescribeLogStreams' | |
Resource: | |
- 'arn:aws:logs:*:*:*' | |
IAMPolicySSHAccess: | |
Type: 'AWS::IAM::Policy' | |
Condition: HasIAMUserSSHAccess | |
Properties: | |
Roles: | |
- !Ref IAMRole | |
PolicyName: iam | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Action: | |
- 'iam:ListUsers' | |
Resource: | |
- '*' | |
- Effect: Allow | |
Action: | |
- 'iam:ListSSHPublicKeys' | |
- 'iam:GetSSHPublicKey' | |
Resource: | |
- !Sub 'arn:aws:iam::${AWS::AccountId}:user/*' | |
TestMachine: | |
Type: 'AWS::EC2::Instance' | |
Metadata: | |
'AWS::CloudFormation::Init': | |
configSets: | |
default: !If [HasIAMUserSSHAccess, [awslogs, ssh-access, config], [awslogs, config]] | |
awslogs: | |
packages: | |
yum: | |
awslogs: [] | |
files: | |
/etc/awslogs/awscli.conf: | |
content: !Sub | | |
[default] | |
region = ${AWS::Region} | |
[plugins] | |
cwlogs = cwlogs | |
mode: '000644' | |
owner: root | |
group: root | |
/etc/awslogs/awslogs.conf: | |
content: !Sub | | |
[general] | |
state_file = /var/lib/awslogs/agent-state | |
[/var/log/messages] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/messages | |
log_stream_name = {instance_id}/var/log/messages | |
log_group_name = ${Logs} | |
[/var/log/secure] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/secure | |
log_stream_name = {instance_id}/var/log/secure | |
log_group_name = ${Logs} | |
[/var/log/cron] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/cron | |
log_stream_name = {instance_id}/var/log/cron | |
log_group_name = ${Logs} | |
[/var/log/cloud-init.log] | |
datetime_format = %b %d %H:%M:%S | |
file = /var/log/cloud-init.log | |
log_stream_name = {instance_id}/var/log/cloud-init.log | |
log_group_name = ${Logs} | |
[/var/log/cfn-init.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-init.log | |
log_stream_name = {instance_id}/var/log/cfn-init.log | |
log_group_name = ${Logs} | |
[/var/log/cfn-hup.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-hup.log | |
log_stream_name = {instance_id}/var/log/cfn-hup.log | |
log_group_name = ${Logs} | |
[/var/log/cfn-init-cmd.log] | |
datetime_format = %Y-%m-%d %H:%M:%S | |
file = /var/log/cfn-init-cmd.log | |
log_stream_name = {instance_id}/var/log/cfn-init-cmd.log | |
log_group_name = ${Logs} | |
[/var/log/cloud-init-output.log] | |
file = /var/log/cloud-init-output.log | |
log_stream_name = {instance_id}/var/log/cloud-init-output.log | |
log_group_name = ${Logs} | |
[/var/log/dmesg] | |
file = /var/log/dmesg | |
log_stream_name = {instance_id}/var/log/dmesg | |
log_group_name = ${Logs} | |
mode: '000644' | |
owner: root | |
group: root | |
services: | |
sysvinit: | |
awslogs: | |
enabled: true | |
ensureRunning: true | |
packages: | |
yum: | |
- awslogs | |
files: | |
- /etc/awslogs/awslogs.conf | |
- /etc/awslogs/awscli.conf | |
ssh-access: | |
files: | |
/opt/authorized_keys_command.sh: | |
content: | | |
#!/bin/bash -e | |
if [ -z "$1" ]; then | |
exit 1 | |
fi | |
UnsaveUserName="$1" | |
UnsaveUserName=${UnsaveUserName//".plus."/"+"} | |
UnsaveUserName=${UnsaveUserName//".equal."/"="} | |
UnsaveUserName=${UnsaveUserName//".comma."/","} | |
UnsaveUserName=${UnsaveUserName//".at."/"@"} | |
aws iam list-ssh-public-keys --user-name "$UnsaveUserName" --query "SSHPublicKeys[?Status == 'Active'].[SSHPublicKeyId]" --output text | while read -r KeyId; do | |
aws iam get-ssh-public-key --user-name "$UnsaveUserName" --ssh-public-key-id "$KeyId" --encoding SSH --query "SSHPublicKey.SSHPublicKeyBody" --output text | |
done | |
mode: '000755' | |
owner: root | |
group: root | |
/opt/import_users.sh: | |
content: | | |
#!/bin/bash -e | |
aws iam list-users --query "Users[].[UserName]" --output text | while read User; do | |
SaveUserName="$User" | |
SaveUserName=${SaveUserName//"+"/".plus."} | |
SaveUserName=${SaveUserName//"="/".equal."} | |
SaveUserName=${SaveUserName//","/".comma."} | |
SaveUserName=${SaveUserName//"@"/".at."} | |
if [ "${#SaveUserName}" -le "32" ]; then | |
if ! id -u "$SaveUserName" >/dev/null 2>&1; then | |
#sudo will read each file in /etc/sudoers.d, skipping file names that end in ‘~’ or contain a ‘.’ character to avoid causing problems with package manager or editor temporary/backup files. | |
SaveUserFileName=$(echo "$SaveUserName" | tr "." " ") | |
/usr/sbin/useradd "$SaveUserName" | |
echo "$SaveUserName ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$SaveUserFileName" | |
fi | |
else | |
echo "Can not import IAM user ${SaveUserName}. User name is longer than 32 characters." | |
fi | |
done | |
mode: '000755' | |
owner: root | |
group: root | |
/etc/cron.d/import_users: | |
content: | | |
*/10 * * * * root /opt/import_users.sh | |
mode: '000644' | |
owner: root | |
group: root | |
commands: | |
a_configure_sshd_command: | |
command: sed -i "s:#AuthorizedKeysCommand none:AuthorizedKeysCommand /opt/authorized_keys_command.sh:g" /etc/ssh/sshd_config | |
b_configure_sshd_commanduser: | |
command: sed -i "s:#AuthorizedKeysCommandUser nobody:AuthorizedKeysCommandUser nobody:g" /etc/ssh/sshd_config | |
c_import_users: | |
command: ./import_users.sh | |
cwd: /opt | |
services: | |
sysvinit: | |
sshd: | |
enabled: true | |
ensureRunning: true | |
commands: | |
- a_configure_sshd_command | |
- b_configure_sshd_commanduser | |
config: | |
files: | |
/etc/cfn/cfn-hup.conf: | |
content: !Sub | | |
[main] | |
stack=${AWS::StackId} | |
region=${AWS::Region} | |
interval=1 | |
mode: '000400' | |
owner: root | |
group: root | |
/etc/cfn/hooks.d/cfn-auto-reloader.conf: | |
content: !Sub | | |
[cfn-auto-reloader-hook] | |
triggers=post.update | |
path=Resources.VirtualMachine.Metadata.AWS::CloudFormation::Init | |
action=/opt/aws/bin/cfn-init --verbose --stack=${AWS::StackName} --region=${AWS::Region} --resource=VirtualMachine | |
runas=root | |
services: | |
sysvinit: | |
cfn-hup: | |
enabled: true | |
ensureRunning: true | |
files: | |
- /etc/cfn/cfn-hup.conf | |
- /etc/cfn/hooks.d/cfn-auto-reloader.conf | |
Properties: | |
IamInstanceProfile: !Ref InstanceProfile | |
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI] | |
InstanceType: !Ref InstanceType | |
SecurityGroupIds: | |
- !Ref SecurityGroup | |
KeyName: !If [HasKeyName, !Ref KeyName, !Ref 'AWS::NoValue'] | |
SubnetId: | |
'Fn::ImportValue': !Sub '${ParentVPCStack}-SubnetAPublic' | |
UserData: | |
'Fn::Base64': !Sub | | |
#!/bin/bash -ex | |
trap '/opt/aws/bin/cfn-signal -e 1 --region ${AWS::Region} --stack ${AWS::StackName} --resource TestMachine' ERR | |
yum update -y | |
yum install -y docker | |
usermod -aG docker ec2-user | |
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource TestMachine --region ${AWS::Region} | |
/opt/aws/bin/cfn-signal -e 0 --region ${AWS::Region} --stack ${AWS::StackName} --resource TestMachine | |
Tags: | |
- Key: Name | |
Value: !Ref Name | |
CreationPolicy: | |
ResourceSignal: | |
Count: 1 | |
Timeout: PT10M | |
Logs: | |
Type: 'AWS::Logs::LogGroup' | |
Properties: | |
RetentionInDays: 14 | |
Outputs: | |
StackName: | |
Description: Stack name. | |
Value: !Sub '${AWS::StackName}' | |
InstanceId: | |
Description: The EC2 instance id. | |
Value: !Ref TestMachine | |
Export: | |
Name: !Sub '${AWS::StackName}-InstanceId' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment