Skip to content

Instantly share code, notes, and snippets.

@OlegGorj
Created March 18, 2018 17:43
Show Gist options
  • Save OlegGorj/32c3ec07f6ad6da5eed8e965f4023538 to your computer and use it in GitHub Desktop.
Save OlegGorj/32c3ec07f6ad6da5eed8e965f4023538 to your computer and use it in GitHub Desktop.
Bastion/Jumphost with TF
variable "tag" {}
variable "vpc_id" {}
variable "cidr" {}
variable "region" {}
variable "image" {}
variable "key_name" {}
variable "instance_type" {}
variable "zone_id" {}
variable "domain" {}
variable "zones" {
type = "list"
default = []
}
variable "subnet_ids" {
type = "list"
default = []
}
/*=== JUMPHOST INSTANCE ASG ===*/
resource "aws_autoscaling_group" "jumphost" {
name = "${var.tag}-jumphost-asg"
availability_zones = ["${var.zones}"]
vpc_zone_identifier = ["${var.subnet_ids}"]
max_size = 1
min_size = 1
health_check_grace_period = 60
default_cooldown = 60
health_check_type = "EC2"
desired_capacity = 1
force_delete = true
launch_configuration = "${aws_launch_configuration.jumphost.name}"
tag {
key = "Name"
value = "JUMPHOST-${var.tag}"
propagate_at_launch = true
}
tag {
key = "Environment"
value = "${lower(var.tag)}"
propagate_at_launch = true
}
tag {
key = "Type"
value = "jumphost"
propagate_at_launch = true
}
tag {
key = "Role"
value = "bastion"
propagate_at_launch = true
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "jumphost" {
name_prefix = "${var.tag}-jumphost-lc-"
image_id = "${var.image}"
instance_type = "${var.instance_type}"
iam_instance_profile = "${aws_iam_instance_profile.jumphost.name}"
key_name = "${var.key_name}"
security_groups = ["${aws_security_group.jumphost.id}"]
associate_public_ip_address = true
user_data = "${data.template_file.jumphost.rendered}"
lifecycle {
create_before_destroy = true
}
}
data "template_file" "jumphost" {
template = "${file("${path.module}/userdata-jumphost.sh")}"
vars {
cidr = "${var.cidr}"
zone_id = "${var.zone_id}"
domain = "${var.domain}"
}
}
/*== JUMPHOST INSTANCES IAM ==*/
resource "aws_iam_instance_profile" "jumphost" {
name = "${var.tag}-jumphost-profile"
roles = ["${aws_iam_role.jumphost.name}"]
lifecycle {
create_before_destroy = true
}
}
resource "aws_iam_role" "jumphost" {
name = "${var.tag}-jumphost-role"
path = "/"
assume_role_policy = "${data.aws_iam_policy_document.jumphost.json}"
lifecycle {
create_before_destroy = true
}
}
data "aws_iam_policy_document" "jumphost" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role_policy" "jumphost-route53" {
name = "${var.tag}-jumphost-role-policy"
role = "${aws_iam_role.jumphost.id}"
policy = "${data.aws_iam_policy_document.jumphost-route53.json}"
}
data "aws_iam_policy_document" "jumphost-route53" {
statement {
sid = "BastionListHostedZones"
effect = "Allow"
resources = ["*"]
actions = [
"route53:ListHostedZones"
]
},
statement {
sid = "BastionChangeRecordSets"
effect = "Allow"
resources = ["arn:aws:route53:::hostedzone/${var.zone_id}"]
actions = [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
]
}
}
/*== JUMPHOST INSTANCES SECURITY GROUP ==*/
resource "aws_security_group" "jumphost" {
name = "${var.tag}-jumphost"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = "${var.vpc_id}"
tags {
Name = "${var.tag}-jumphost-security-group"
Environment = "${lower(var.tag)}"
}
}
output "bastion_sg_id" { value = "${aws_security_group.jumphost.id}" }
output "bastion_asg_id" { value = "${aws_autoscaling_group.jumphost.id}" }
output "bastion_lc_id" { value = "${aws_launch_configuration.jumphost.id}" }
output "bastion_iam_arn" { value = "${aws_iam_role.jumphost.arn}" }
#!/bin/bash -v
set -ex
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | debconf-set-selections
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | debconf-set-selections
rm -rf /var/lib/apt/lists/*
sed -e '/^deb.*security/ s/^/#/g' -i /etc/apt/sources.list
export DEBIAN_FRONTEND=noninteractive
apt-get update -y -m -qq && apt-get upgrade -y -m -qq
apt-get -y --force-yes install awscli conntrack iptables-persistent nfs-common jq unzip curl > /tmp/bastion.log
[[ -s $(modinfo -n ip_conntrack) ]] && modprobe ip_conntrack && echo ip_conntrack | tee -a /etc/modules
/sbin/sysctl -w net.ipv4.conf.eth0.send_redirects=0
/sbin/sysctl -w net.netfilter.nf_conntrack_max=131072
echo "net.ipv4.conf.eth0.send_redirects=0" >> /etc/sysctl.conf
echo "net.netfilter.nf_conntrack_max=131072" >> /etc/sysctl.conf
/sbin/iptables -A INPUT -m state --state INVALID -j DROP
/sbin/iptables -A FORWARD -m state --state INVALID -j DROP
/sbin/iptables -A INPUT -p tcp --syn -m limit --limit 5/s -i eth0 -j ACCEPT
/sbin/iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sleep 1
cat > /etc/profile.d/user.sh <<END
HISTSIZE=1000
HISTFILESIZE=40000
HISTTIMEFORMAT="[%F %T %Z] "
export HISTSIZE HISTFILESIZE HISTTIMEFORMAT
END
# Instance Metadata
HOSTNAME=$(hostname -f)
URL="http://169.254.169.254/latest"
ID=$(curl -s $URL/meta-data/instance-id)
REGION=$(curl -s $URL/dynamic/instance-identity/document | jq -r '.region')
IP=$(curl -s $URL/meta-data/local-ipv4)
STS_IAM_ARN=$(curl -s $URL/meta-data/iam/info | jq -c -M -r '.InstanceProfileArn')
# Insert/Update Route53 internal zone DNS record
cat > /root/record.json <<END
{
"Comment": "Bastion Route53 internal zone record",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "bastion.${domain}",
"Type": "A",
"TTL": 30,
"ResourceRecords": [
{
"Value": "$${IP}"
}
]
}
}
]
}
END
aws route53 change-resource-record-sets --hosted-zone-id "${zone_id}" --change-batch file:///root/record.json | tee -a /tmp/bastion.log
sed -e '/^#deb.*security/ s/^#//g' -i /etc/apt/sources.list
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment