Last active
March 23, 2018 06:36
-
-
Save antklim/2469dc4f099dc2723b78e84c8d2bf0bc to your computer and use it in GitHub Desktop.
This file contains hidden or 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
Description: This template deploys bastion instance for SimpleAPI | |
Parameters: | |
BastionSecurityGroup: | |
Description: A reference to the security group for Bastion host | |
Type: String | |
Environment: | |
Description: An environment name that will be prefixed to resource names | |
Type: String | |
KeyName: | |
Description: EC2 key pair name for bastion host SSH access | |
Type: AWS::EC2::KeyPair::KeyName | |
LogRetentionInDays: | |
Description: Number of days you would like your CloudWatch Logs to be retained | |
Type: Number | |
Default: 90 | |
Namespace: | |
Description: An infrastructure namespace that will be prefixed to resource names | |
Type: String | |
Default: simple-api | |
PublicSubnet: | |
Description: A reference to the public subnet in the VPC | |
Type: String | |
Mappings: | |
# Please add your region to mapping | |
AWSRegionToAMI: | |
ap-southeast-2: | |
AMI: ami-942dd1f6 | |
Resources: | |
############################################################################## | |
# Bastion instance | |
############################################################################## | |
BastionHost: | |
Type: AWS::EC2::Instance | |
DependsOn: BastionEipAssociation | |
Metadata: | |
AWS::CloudFormation::Init: | |
config: | |
packages: | |
yum: | |
awslogs: [] | |
files: | |
"/etc/cfn/cfn-hup.conf": | |
mode: "000444" | |
owner: root | |
group: root | |
content: !Sub | | |
[main] | |
stack=${AWS::StackId} | |
region=${AWS::Region} | |
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": | |
mode: "000444" | |
owner: root | |
group: root | |
content: !Sub | | |
[cfn-auto-reloader-hook] | |
triggers=post.update | |
path=Resources.BastionHost.Metadata.AWS::CloudFormation::Init | |
action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource BastionHost --region ${AWS::Region} | |
"/etc/awslogs/awslogs.conf": | |
mode: "000444" | |
owner: root | |
group: root | |
content: !Sub | | |
[general] | |
use_gzip_http_content_encoding = true | |
state_file = /var/lib/awslogs/agent-state | |
[/var/log/secure] | |
file = /var/log/secure | |
log_group_name = ${BastionLogGroup} | |
log_stream_name = log | |
datetime_format = %b %d %H:%M:%S | |
"/etc/awslogs/awscli.conf": | |
mode: "000444" | |
owner: root | |
group: root | |
content: !Sub | | |
[plugins] | |
cwlogs = cwlogs | |
[default] | |
region = ${AWS::Region} | |
services: | |
sysvinit: | |
cfn-hup: | |
enabled: true | |
ensureRunning: true | |
files: | |
- /etc/cfn/cfn-hup.conf | |
- /etc/cfn/hooks.d/cfn-auto-reloader.conf | |
awslogs: | |
enabled: true | |
ensureRunning: true | |
files: /etc/awslogs/awslogs.conf | |
Properties: | |
InstanceType: t2.micro | |
KeyName: !Ref KeyName | |
NetworkInterfaces: | |
- NetworkInterfaceId: !Ref BastionNetworkInterface | |
DeviceIndex: 0 | |
ImageId: !FindInMap [ AWSRegionToAMI, !Ref "AWS::Region", AMI ] | |
UserData: | |
Fn::Base64: !Sub | | |
#!/bin/bash -xe | |
yum update -y | |
/opt/aws/bin/cfn-init -v -s ${AWS::StackId} --resource BastionHost --region ${AWS::Region} | |
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource BastionHost --region ${AWS::Region} | |
IamInstanceProfile: !Ref BastionInstanceProfile | |
Tags: | |
- Key: Name | |
Value: !Sub ${Namespace}-${Environment}-bastion | |
CreationPolicy: | |
ResourceSignal: | |
Count: 1 | |
Timeout: PT5M | |
############################################################################## | |
# Bastion elastic IP and network interface | |
############################################################################## | |
BastionEip: | |
Type: AWS::EC2::EIP | |
Properties: | |
Domain: vpc | |
BastionEipAssociation: | |
Type: AWS::EC2::EIPAssociation | |
Properties: | |
AllocationId: !GetAtt BastionEip.AllocationId | |
NetworkInterfaceId: !Ref BastionNetworkInterface | |
DependsOn: | |
- BastionEip | |
- BastionNetworkInterface | |
BastionNetworkInterface: | |
Type: AWS::EC2::NetworkInterface | |
Properties: | |
SubnetId: !Ref PublicSubnet | |
GroupSet: | |
- !Ref BastionSecurityGroup | |
SourceDestCheck: true | |
Tags: | |
- Key: Name | |
Value: bastion-network-interface | |
############################################################################## | |
# Bastion role | |
############################################################################## | |
BastionRole: | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: ec2.amazonaws.com | |
Action: sts:AssumeRole | |
Path: / | |
Policies: | |
- PolicyName: CloudWatchLogs | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Action: | |
- logs:DescribeLogStreams | |
- logs:PutLogEvents | |
Resource: !GetAtt BastionLogGroup.Arn | |
BastionInstanceProfile: | |
Type: AWS::IAM::InstanceProfile | |
Properties: | |
Path: / | |
Roles: | |
- !Ref BastionRole | |
############################################################################## | |
# Bastion logs | |
############################################################################## | |
BastionLogGroup: | |
Type: AWS::Logs::LogGroup | |
Properties: | |
RetentionInDays: !Ref LogRetentionInDays | |
BastionLogGroupStream: | |
Type: AWS::Logs::LogStream | |
Properties: | |
LogGroupName: !Ref BastionLogGroup | |
LogStreamName: log | |
############################################################################## | |
# Bastion alarms | |
############################################################################## | |
# When a user tries to SSH with invalid username the activity is logged in the SSH log file | |
SshInvalidUserMetricFilter: | |
Type: AWS::Logs::MetricFilter | |
Properties: | |
LogGroupName: !Ref BastionLogGroup | |
FilterPattern: "[Mon, day, timestamp, ip, id, status = Invalid, ...]" | |
MetricTransformations: | |
- MetricValue: 1 | |
MetricNamespace: SSH | |
MetricName: sshInvalidUser | |
SshInvalidhUserAlarm: | |
Type: AWS::CloudWatch::Alarm | |
Properties: | |
AlarmDescription: SSH connections attempted with invalid username is greater than 3 over 1 minutes | |
MetricName: sshInvalidUser | |
Namespace: SSH | |
Statistic: Sum | |
Period: 60 | |
EvaluationPeriods: 1 | |
Threshold: 3 | |
ComparisonOperator: GreaterThanThreshold | |
TreatMissingData: notBreaching | |
# When a user uses a bad private key pair or username | |
SshClosedConnectionMetricFilter: | |
Type: AWS::Logs::MetricFilter | |
Properties: | |
LogGroupName: !Ref BastionLogGroup | |
FilterPattern: "[Mon, day, timestamp, ip, id, msg1= Connection, msg2 = closed, ...]" | |
MetricTransformations: | |
- MetricValue: 1 | |
MetricNamespace: SSH | |
MetricName: sshClosedConnection | |
SshClosedConnectionAlarm: | |
Type: AWS::CloudWatch::Alarm | |
Properties: | |
AlarmDescription: SSH connections closed due to invalid SSH key or username is greater than 5 in 5 minutes | |
MetricName: sshClosedConnection | |
Namespace: SSH | |
Statistic: Sum | |
Period: 300 | |
EvaluationPeriods: 1 | |
Threshold: 5 | |
ComparisonOperator: GreaterThanThreshold | |
TreatMissingData: notBreaching | |
Outputs: | |
BastionEip: | |
Description: EIP for bastion host | |
Value: !Ref BastionEip |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment