├── ec2_simple ├── files │ ├── import_users.cron │ ├── import_users.sh │ ├── authorized_keys_command.sh │ └── install.sh ├── aws.tf ├── resources │ ├── iam_assume_role_policy.json │ └── iam_role_policy.template.json ├── secret.sample.tfvars ├── Makefile ├── iam.tf ├── security.tf ├── variables.tf └── ec2.tf ├── ec2_vpc ├── files │ ├── import_users.cron │ ├── import_users.sh │ ├── authorized_keys_command.sh │ └── install.sh ├── aws.tf ├── resources │ ├── iam_assume_role_policy.json │ └── iam_role_policy.template.json ├── secret.sample.tfvars ├── Makefile ├── iam.tf ├── variables.tf ├── ec2.tf └── security.tf ├── ec2_simple_nokey ├── files │ ├── import_users.cron │ ├── authorized_keys_command.sh │ ├── import_users.sh │ └── install.sh ├── aws.tf ├── secret.sample.tfvars ├── resources │ ├── iam_assume_role_policy.json │ ├── instance_user_data.sh │ └── iam_role_policy.template.json ├── Makefile ├── iam.tf ├── security.tf ├── ec2.tf └── variables.tf ├── ec2_vpc_nokey ├── files │ ├── import_users.cron │ ├── import_users.sh │ ├── authorized_keys_command.sh │ └── install.sh ├── aws.tf ├── secret.sample.tfvars ├── resources │ ├── iam_assume_role_policy.json │ ├── instance_user_data.sh │ └── iam_role_policy.template.json ├── Makefile ├── iam.tf ├── ec2.tf ├── variables.tf └── security.tf ├── .gitignore ├── docs ├── sequence.png ├── aws-entities-1.png └── aws-entities-2.png ├── LICENSE └── README.md /ec2_simple/files/import_users.cron: -------------------------------------------------------------------------------- 1 | */10 * * * * root /opt/import_users.sh -------------------------------------------------------------------------------- /ec2_vpc/files/import_users.cron: -------------------------------------------------------------------------------- 1 | */10 * * * * root /opt/import_users.sh -------------------------------------------------------------------------------- /ec2_simple_nokey/files/import_users.cron: -------------------------------------------------------------------------------- 1 | */10 * * * * root /opt/import_users.sh -------------------------------------------------------------------------------- /ec2_vpc_nokey/files/import_users.cron: -------------------------------------------------------------------------------- 1 | */10 * * * * root /opt/import_users.sh -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | secret.tfvars 2 | .idea/ 3 | *.iml 4 | terraform.tfstate* 5 | *.tfplan -------------------------------------------------------------------------------- /docs/sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/aws-ec2-ssh-sync/master/docs/sequence.png -------------------------------------------------------------------------------- /docs/aws-entities-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/aws-ec2-ssh-sync/master/docs/aws-entities-1.png -------------------------------------------------------------------------------- /docs/aws-entities-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/aws-ec2-ssh-sync/master/docs/aws-entities-2.png -------------------------------------------------------------------------------- /ec2_vpc/aws.tf: -------------------------------------------------------------------------------- 1 | 2 | provider "aws" { 3 | access_key = "${var.aws_access_key}" 4 | secret_key = "${var.aws_secret_key}" 5 | region = "${var.aws_region}" 6 | } 7 | -------------------------------------------------------------------------------- /ec2_simple/aws.tf: -------------------------------------------------------------------------------- 1 | 2 | provider "aws" { 3 | access_key = "${var.aws_access_key}" 4 | secret_key = "${var.aws_secret_key}" 5 | region = "${var.aws_region}" 6 | } 7 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/aws.tf: -------------------------------------------------------------------------------- 1 | 2 | provider "aws" { 3 | access_key = "${var.aws_access_key}" 4 | secret_key = "${var.aws_secret_key}" 5 | region = "${var.aws_region}" 6 | } 7 | -------------------------------------------------------------------------------- /ec2_simple_nokey/aws.tf: -------------------------------------------------------------------------------- 1 | 2 | provider "aws" { 3 | access_key = "${var.aws_access_key}" 4 | secret_key = "${var.aws_secret_key}" 5 | region = "${var.aws_region}" 6 | } 7 | -------------------------------------------------------------------------------- /ec2_simple_nokey/secret.sample.tfvars: -------------------------------------------------------------------------------- 1 | # Copy this to secrets.tfvars to setup your own credentials 2 | 3 | aws_access_key="PUT_YOUR_ACCESS_KEY" 4 | aws_secret_key="PUT_YOUR_SECRET_KEY" 5 | aws_account="PUT_YOUR_AWS_ACCOUNT" 6 | aws_region="us-east-1" 7 | private_key_name="mykey" 8 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/secret.sample.tfvars: -------------------------------------------------------------------------------- 1 | # Copy this to secrets.tfvars to setup your own credentials 2 | 3 | aws_access_key="PUT_YOUR_ACCESS_KEY" 4 | aws_secret_key="PUT_YOUR_SECRET_KEY" 5 | aws_account="PUT_YOUR_AWS_ACCOUNT" 6 | aws_region="us-east-1" 7 | private_key_name="mykey" 8 | private_key_path="/Users/bob/.ssh/ec2Key" -------------------------------------------------------------------------------- /ec2_vpc/resources/iam_assume_role_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": [ 8 | "ec2.amazonaws.com" 9 | ] 10 | }, 11 | "Action": [ 12 | "sts:AssumeRole" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /ec2_simple/files/import_users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | aws iam list-users --query "Users[].[UserName]" --output text | while read User; do 4 | if id -u "$User" >/dev/null 2>&1; then 5 | echo "$User exists" 6 | else 7 | /usr/sbin/adduser "$User" 8 | echo "$User ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$User" 9 | fi 10 | done 11 | -------------------------------------------------------------------------------- /ec2_simple/resources/iam_assume_role_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": [ 8 | "ec2.amazonaws.com" 9 | ] 10 | }, 11 | "Action": [ 12 | "sts:AssumeRole" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /ec2_vpc/files/import_users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | aws iam list-users --query "Users[].[UserName]" --output text | while read User; do 4 | if id -u "$User" >/dev/null 2>&1; then 5 | echo "$User exists" 6 | else 7 | /usr/sbin/adduser "$User" 8 | echo "$User ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$User" 9 | fi 10 | done 11 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/resources/iam_assume_role_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": [ 8 | "ec2.amazonaws.com" 9 | ] 10 | }, 11 | "Action": [ 12 | "sts:AssumeRole" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /ec2_simple_nokey/resources/iam_assume_role_policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Principal": { 7 | "Service": [ 8 | "ec2.amazonaws.com" 9 | ] 10 | }, 11 | "Action": [ 12 | "sts:AssumeRole" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /ec2_vpc_nokey/files/import_users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | aws iam list-users --query "Users[].[UserName]" --output text | while read User; do 4 | if id -u "$User" >/dev/null 2>&1; then 5 | echo "$User exists" 6 | else 7 | /usr/sbin/adduser "$User" 8 | echo "$User ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$User" 9 | fi 10 | done 11 | -------------------------------------------------------------------------------- /ec2_simple/secret.sample.tfvars: -------------------------------------------------------------------------------- 1 | # Copy this to secrets.tfvars to setup your own credentials 2 | 3 | aws_access_key="PUT_YOUR_ACCESS_KEY" 4 | aws_secret_key="PUT_YOUR_SECRET_KEY" 5 | aws_account="PUT_YOUR_AWS_ACCOUNT" 6 | aws_region="us-east-1" 7 | # Name of the ec2 keypair for that region 8 | private_key_name="mykey" 9 | # Path to the private key on your hard drive 10 | private_key_path="/Users/bob/.ssh/ec2Key" -------------------------------------------------------------------------------- /ec2_vpc/secret.sample.tfvars: -------------------------------------------------------------------------------- 1 | # Copy this to secrets.tfvars to setup your own credentials 2 | 3 | aws_access_key="PUT_YOUR_ACCESS_KEY" 4 | aws_secret_key="PUT_YOUR_SECRET_KEY" 5 | aws_account="PUT_YOUR_AWS_ACCOUNT" 6 | aws_region="us-east-1" 7 | # Name of the ec2 keypair for that region 8 | private_key_name="mykey" 9 | # Path to the private key on your hard drive 10 | private_key_path="/Users/bob/.ssh/ec2Key" -------------------------------------------------------------------------------- /ec2_simple/files/authorized_keys_command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if [ -z "$1" ]; then 4 | exit 1 5 | fi 6 | 7 | aws iam list-ssh-public-keys --user-name "$1" --query "SSHPublicKeys[?Status == 'Active'].[SSHPublicKeyId]" --output text | while read KeyId; do 8 | aws iam get-ssh-public-key --user-name "$1" --ssh-public-key-id "$KeyId" --encoding SSH --query "SSHPublicKey.SSHPublicKeyBody" --output text 9 | done 10 | -------------------------------------------------------------------------------- /ec2_vpc/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all plan apply destroy refresh 2 | 3 | all: plan apply 4 | 5 | refresh: 6 | terraform refresh -var-file secret.tfvars 7 | 8 | plan: 9 | terraform plan -var-file secret.tfvars -out terraform.tfplan 10 | 11 | apply: 12 | terraform apply -var-file secret.tfvars 13 | 14 | destroy: 15 | terraform plan -destroy -var-file secret.tfvars -out terraform.tfplan 16 | terraform apply terraform.tfplan -------------------------------------------------------------------------------- /ec2_vpc/files/authorized_keys_command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if [ -z "$1" ]; then 4 | exit 1 5 | fi 6 | 7 | aws iam list-ssh-public-keys --user-name "$1" --query "SSHPublicKeys[?Status == 'Active'].[SSHPublicKeyId]" --output text | while read KeyId; do 8 | aws iam get-ssh-public-key --user-name "$1" --ssh-public-key-id "$KeyId" --encoding SSH --query "SSHPublicKey.SSHPublicKeyBody" --output text 9 | done 10 | -------------------------------------------------------------------------------- /ec2_simple/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all plan apply destroy refresh 2 | 3 | all: plan apply 4 | 5 | refresh: 6 | terraform refresh -var-file secret.tfvars 7 | 8 | plan: 9 | terraform plan -var-file secret.tfvars -out terraform.tfplan 10 | 11 | apply: 12 | terraform apply -var-file secret.tfvars 13 | 14 | destroy: 15 | terraform plan -destroy -var-file secret.tfvars -out terraform.tfplan 16 | terraform apply terraform.tfplan -------------------------------------------------------------------------------- /ec2_vpc_nokey/files/authorized_keys_command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if [ -z "$1" ]; then 4 | exit 1 5 | fi 6 | 7 | aws iam list-ssh-public-keys --user-name "$1" --query "SSHPublicKeys[?Status == 'Active'].[SSHPublicKeyId]" --output text | while read KeyId; do 8 | aws iam get-ssh-public-key --user-name "$1" --ssh-public-key-id "$KeyId" --encoding SSH --query "SSHPublicKey.SSHPublicKeyBody" --output text 9 | done 10 | -------------------------------------------------------------------------------- /ec2_simple_nokey/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all plan apply destroy refresh 2 | 3 | all: plan apply 4 | 5 | refresh: 6 | terraform refresh -var-file secret.tfvars 7 | 8 | plan: 9 | terraform plan -var-file secret.tfvars -out terraform.tfplan 10 | 11 | apply: 12 | terraform apply -var-file secret.tfvars 13 | 14 | destroy: 15 | terraform plan -destroy -var-file secret.tfvars -out terraform.tfplan 16 | terraform apply terraform.tfplan -------------------------------------------------------------------------------- /ec2_simple_nokey/files/authorized_keys_command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if [ -z "$1" ]; then 4 | exit 1 5 | fi 6 | 7 | aws iam list-ssh-public-keys --user-name "$1" --query "SSHPublicKeys[?Status == 'Active'].[SSHPublicKeyId]" --output text | while read KeyId 8 | do 9 | aws iam get-ssh-public-key --user-name "$1" --ssh-public-key-id "$KeyId" --encoding SSH --query "SSHPublicKey.SSHPublicKeyBody" --output text 10 | done 11 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all plan apply destroy refresh 2 | 3 | all: plan apply 4 | 5 | refresh: 6 | terraform refresh -var-file secret.tfvars 7 | 8 | plan: 9 | terraform plan -var-file secret.tfvars -out terraform.tfplan 10 | 11 | apply: 12 | terraform apply -var-file secret.tfvars 13 | 14 | destroy: 15 | terraform plan -destroy -var-file secret.tfvars -out terraform.tfplan 16 | terraform apply terraform.tfplan -------------------------------------------------------------------------------- /ec2_simple_nokey/files/import_users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | aws iam list-users --query "Users[].[UserName]" --output text | while read User; do 4 | if id -u "$User" >/dev/null 2>&1; then 5 | echo "$User exists" 6 | else 7 | source /etc/os-release 8 | if [ "$NAME" == "Ubuntu" ] || [ "$NAME" == "Debian GNU/Linux" ]; then 9 | /usr/sbin/useradd -m "$User" -s /bin/bash 10 | elif [ "$NAME" == "Amazon Linux AMI" ]; then 11 | /usr/sbin/adduser "$User" 12 | fi 13 | echo "$User ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$User" 14 | fi 15 | done 16 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/resources/instance_user_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install Git 4 | sudo yum install -y git 5 | 6 | # Fetch setup files from Github over HTTPS. You can choose any other secure way to fetch your setup files 7 | cd /tmp 8 | mkdir setup 9 | cd setup/ 10 | git init 11 | git remote add -f origin https://github.com/sportebois/aws-ec2-ssh-sync.git 12 | git config core.sparseCheckout true 13 | #echo "ec2_vpc_nokey/files/" >> .git/info/sparse-checkout 14 | echo "ec2_vpc/files/" >> .git/info/sparse-checkout 15 | git pull --depth=1 origin master 16 | 17 | # Then run the setup 18 | #cd ec2_vpc_nokey/files 19 | cd ec2_vpc/files 20 | chmod +x *.sh 21 | sudo ./install.sh 22 | -------------------------------------------------------------------------------- /ec2_simple/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install PIP to be able to install the AWS Cli (later used to get the ssh keys) 4 | #curl -O https://bootstrap.pypa.io/get-pip.py 5 | #sudo python27 get-pip.py 6 | #sudo /usr/local/bin/pip install awscli 7 | 8 | sudo yum update -y 9 | sudo yum install aws-cli -y 10 | 11 | sudo cp authorized_keys_command.sh /opt/authorized_keys_command.sh 12 | sudo cp import_users.sh /opt/import_users.sh 13 | 14 | sudo sed -i 's:#AuthorizedKeysCommand none:AuthorizedKeysCommand /opt/authorized_keys_command.sh:g' /etc/ssh/sshd_config 15 | sudo sed -i 's:#AuthorizedKeysCommandUser nobody:AuthorizedKeysCommandUser nobody:g' /etc/ssh/sshd_config 16 | 17 | # Refresh users frequently 18 | sudo cp import_users.cron /etc/cron.d/import_users 19 | sudo chmod 0644 /etc/cron.d/import_users 20 | 21 | # Run it immediately 22 | sudo /opt/import_users.sh 23 | 24 | sudo service sshd restart 25 | -------------------------------------------------------------------------------- /ec2_vpc/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install PIP to be able to install the AWS Cli (later used to get the ssh keys) 4 | #curl -O https://bootstrap.pypa.io/get-pip.py 5 | #sudo python27 get-pip.py 6 | #sudo /usr/local/bin/pip install awscli 7 | 8 | sudo yum update -y 9 | sudo yum install aws-cli -y 10 | 11 | sudo cp authorized_keys_command.sh /opt/authorized_keys_command.sh 12 | sudo cp import_users.sh /opt/import_users.sh 13 | 14 | sudo sed -i 's:#AuthorizedKeysCommand none:AuthorizedKeysCommand /opt/authorized_keys_command.sh:g' /etc/ssh/sshd_config 15 | sudo sed -i 's:#AuthorizedKeysCommandUser nobody:AuthorizedKeysCommandUser nobody:g' /etc/ssh/sshd_config 16 | 17 | # Refresh users frequently 18 | sudo cp import_users.cron /etc/cron.d/import_users 19 | sudo chmod 0644 /etc/cron.d/import_users 20 | 21 | # Run it immediately 22 | sudo /opt/import_users.sh 23 | 24 | sudo service sshd restart 25 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install PIP to be able to install the AWS Cli (later used to get the ssh keys) 4 | #curl -O https://bootstrap.pypa.io/get-pip.py 5 | #sudo python27 get-pip.py 6 | #sudo /usr/local/bin/pip install awscli 7 | 8 | sudo yum update -y 9 | sudo yum install aws-cli -y 10 | 11 | sudo cp authorized_keys_command.sh /opt/authorized_keys_command.sh 12 | sudo cp import_users.sh /opt/import_users.sh 13 | 14 | sudo sed -i 's:#AuthorizedKeysCommand none:AuthorizedKeysCommand /opt/authorized_keys_command.sh:g' /etc/ssh/sshd_config 15 | sudo sed -i 's:#AuthorizedKeysCommandUser nobody:AuthorizedKeysCommandUser nobody:g' /etc/ssh/sshd_config 16 | 17 | # Refresh users frequently 18 | sudo cp import_users.cron /etc/cron.d/import_users 19 | sudo chmod 0644 /etc/cron.d/import_users 20 | 21 | # Run it immediately 22 | sudo /opt/import_users.sh 23 | 24 | sudo service sshd restart 25 | -------------------------------------------------------------------------------- /ec2_simple_nokey/files/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install AWS Cli 4 | source /etc/os-release 5 | if [ "$NAME" == "Ubuntu" ] || [ "$NAME" == "Debian GNU/Linux" ]; then 6 | ssh_service="ssh" 7 | sudo apt-get update 8 | sudo apt-get -y install python-pip 9 | sudo pip install awscli 10 | elif [ "$NAME" == "Amazon Linux AMI" ]; then 11 | ssh_service="sshd" 12 | sudo yum update -y 13 | sudo yum install aws-cli -y 14 | fi 15 | 16 | sudo cp authorized_keys_command.sh /opt/authorized_keys_command.sh 17 | sudo cp import_users.sh /opt/import_users.sh 18 | 19 | sudo echo -e "\nAuthorizedKeysCommand /opt/authorized_keys_command.sh" >> /etc/ssh/sshd_config 20 | sudo echo -e "\nAuthorizedKeysCommandUser nobody" >> /etc/ssh/sshd_config 21 | 22 | # Refresh users frequently 23 | sudo cp import_users.cron /etc/cron.d/import_users 24 | sudo chmod 0644 /etc/cron.d/import_users 25 | 26 | # Run it immediately 27 | sudo /opt/import_users.sh 28 | 29 | sudo service $ssh_service restart 30 | -------------------------------------------------------------------------------- /ec2_vpc/iam.tf: -------------------------------------------------------------------------------- 1 | 2 | # Caveat: AWS instance profiles only allows 1 role/1 profile 3 | # "Roles in an instance profile: 1 (each instance profile can contain only 1 role)" 4 | # Learn more: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html 5 | 6 | 7 | resource "aws_iam_role" "ssh" { 8 | name = "ssh" 9 | assume_role_policy = "${file("resources/iam_assume_role_policy.json")}" 10 | } 11 | 12 | 13 | resource "aws_iam_role_policy" "ssh" { 14 | name = "ssh" 15 | role = "${aws_iam_role.ssh.id}" 16 | policy = "${data.template_file.iam_role_policy.rendered}" 17 | } 18 | 19 | 20 | resource "aws_iam_instance_profile" "ssh_test_demo" { 21 | name = "ssh_test_demo" 22 | roles = ["${aws_iam_role.ssh.name}"] 23 | } 24 | 25 | 26 | # The policy json has some dynamic content, like our AWS account. 27 | data "template_file" "iam_role_policy" { 28 | template = "${file("resources/iam_role_policy.template.json")}" 29 | 30 | vars { 31 | aws_account = "${var.aws_account}" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ec2_simple/iam.tf: -------------------------------------------------------------------------------- 1 | 2 | # Caveat: AWS instance profiles oonly allows 1 role/1 profile 3 | # "Roles in an instance profile: 1 (each instance profile can contain only 1 role)" 4 | # Learn more: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html 5 | 6 | 7 | resource "aws_iam_role" "ssh" { 8 | name = "ssh" 9 | assume_role_policy = "${file("resources/iam_assume_role_policy.json")}" 10 | } 11 | 12 | 13 | resource "aws_iam_role_policy" "ssh" { 14 | name = "ssh" 15 | role = "${aws_iam_role.ssh.id}" 16 | policy = "${data.template_file.iam_role_policy.rendered}" 17 | } 18 | 19 | 20 | resource "aws_iam_instance_profile" "ssh_test_demo" { 21 | name = "ssh_test_demo" 22 | roles = ["${aws_iam_role.ssh.name}"] 23 | } 24 | 25 | 26 | # The policy json has some dynamic content, like our AWS account. 27 | data "template_file" "iam_role_policy" { 28 | template = "${file("resources/iam_role_policy.template.json")}" 29 | 30 | vars { 31 | aws_account = "${var.aws_account}" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ec2_simple_nokey/iam.tf: -------------------------------------------------------------------------------- 1 | 2 | # Caveat: AWS instance profiles oonly allows 1 role/1 profile 3 | # "Roles in an instance profile: 1 (each instance profile can contain only 1 role)" 4 | # Learn more: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html 5 | 6 | 7 | resource "aws_iam_role" "ssh" { 8 | name = "ssh" 9 | assume_role_policy = "${file("resources/iam_assume_role_policy.json")}" 10 | } 11 | 12 | 13 | resource "aws_iam_role_policy" "ssh" { 14 | name = "ssh" 15 | role = "${aws_iam_role.ssh.id}" 16 | policy = "${data.template_file.iam_role_policy.rendered}" 17 | } 18 | 19 | 20 | resource "aws_iam_instance_profile" "ssh_test_demo" { 21 | name = "ssh_test_demo" 22 | roles = ["${aws_iam_role.ssh.name}"] 23 | } 24 | 25 | 26 | # The policy json has some dynamic content, like our AWS account. 27 | data "template_file" "iam_role_policy" { 28 | template = "${file("resources/iam_role_policy.template.json")}" 29 | 30 | vars { 31 | aws_account = "${var.aws_account}" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/iam.tf: -------------------------------------------------------------------------------- 1 | 2 | # Caveat: AWS instance profiles oonly allows 1 role/1 profile 3 | # "Roles in an instance profile: 1 (each instance profile can contain only 1 role)" 4 | # Learn more: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html 5 | 6 | 7 | resource "aws_iam_role" "ssh" { 8 | name = "ssh" 9 | assume_role_policy = "${file("resources/iam_assume_role_policy.json")}" 10 | } 11 | 12 | 13 | resource "aws_iam_role_policy" "ssh" { 14 | name = "ssh" 15 | role = "${aws_iam_role.ssh.id}" 16 | policy = "${data.template_file.iam_role_policy.rendered}" 17 | } 18 | 19 | 20 | resource "aws_iam_instance_profile" "ssh_test_demo" { 21 | name = "ssh_test_demo" 22 | roles = ["${aws_iam_role.ssh.name}"] 23 | } 24 | 25 | 26 | # The policy json has some dynamic content, like our AWS account. 27 | data "template_file" "iam_role_policy" { 28 | template = "${file("resources/iam_role_policy.template.json")}" 29 | 30 | vars { 31 | aws_account = "${var.aws_account}" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ec2_simple_nokey/resources/instance_user_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install Git 4 | source /etc/os-release 5 | if [ "$NAME" == "Ubuntu" ] || [ "$NAME" == "Debian GNU/Linux" ]; then 6 | sudo apt-get -y install git 7 | elif [ "$NAME" == "Amazon Linux AMI" ]; then 8 | sudo yum install -y git 9 | fi 10 | 11 | # Fetch setup files from Github over HTTPS. You can choose any other secure way to fetch your setup files 12 | cd /tmp 13 | mkdir setup 14 | cd setup/ 15 | git init 16 | git remote add -f origin https://github.com/sportebois/aws-ec2-ssh-sync.git 17 | git config core.sparseCheckout true 18 | echo "ec2_simple_nokey/files/" >> .git/info/sparse-checkout 19 | git pull --depth=1 origin master 20 | 21 | # Then run the setup 22 | cd ec2_simple_nokey/files 23 | chmod +x *.sh 24 | sudo ./install.sh 25 | 26 | # In some real ECS use, you'd might want to add the following lines and use a Terraform template_file (or directly the value) 27 | # Make sure the instance has the correct cluster registered 28 | # echo ECS_CLUSTER=${ecs_cluster_name} >> /etc/ecs/ecs.config 29 | -------------------------------------------------------------------------------- /ec2_simple/security.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | # --- A security group is needed only to be able to connect to our instance 4 | resource "aws_security_group" "ssh_test_demo" { 5 | name = "ssh_test_demo" 6 | description = "Allow all inbound traffic" 7 | 8 | // Note: For ecs usage, Https outboud traffic to ssm.us-east-1.amazonaws.com and https://ecs.us-east-1.amazonaws.com must be allowed 9 | 10 | # SSH config 11 | ingress { 12 | from_port = 22 13 | to_port = 22 14 | protocol = "tcp" 15 | cidr_blocks = "${var.admin_public_ips}" 16 | } 17 | 18 | # Web traffic 19 | ingress { 20 | from_port = 443 21 | to_port = 443 22 | protocol = "tcp" 23 | cidr_blocks = ["0.0.0.0/0"] 24 | } 25 | 26 | ingress { 27 | from_port = 80 28 | to_port = 80 29 | protocol = "tcp" 30 | cidr_blocks = ["0.0.0.0/0"] 31 | } 32 | 33 | egress { 34 | from_port = 0 35 | to_port = 0 36 | protocol = "-1" 37 | cidr_blocks = ["0.0.0.0/0"] 38 | } 39 | 40 | tags { 41 | Scope = "ssh_test_demo" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ec2_simple_nokey/security.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | # --- A security group is needed only to be able to connect to our instance 4 | resource "aws_security_group" "ssh_test_demo" { 5 | name = "ssh_test_demo" 6 | description = "Allow all inbound traffic" 7 | 8 | // Note: For ecs usage, Https outbound traffic to ssm.us-east-1.amazonaws.com and https://ecs.us-east-1.amazonaws.com must be allowed 9 | 10 | # SSH config 11 | ingress { 12 | from_port = 22 13 | to_port = 22 14 | protocol = "tcp" 15 | cidr_blocks = "${var.admin_public_ips}" 16 | } 17 | 18 | # Web traffic 19 | ingress { 20 | from_port = 443 21 | to_port = 443 22 | protocol = "tcp" 23 | cidr_blocks = ["0.0.0.0/0"] 24 | } 25 | 26 | ingress { 27 | from_port = 80 28 | to_port = 80 29 | protocol = "tcp" 30 | cidr_blocks = ["0.0.0.0/0"] 31 | } 32 | 33 | egress { 34 | from_port = 0 35 | to_port = 0 36 | protocol = "-1" 37 | cidr_blocks = ["0.0.0.0/0"] 38 | } 39 | 40 | tags { 41 | Scope = "ssh_test_demo" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ec2_simple/variables.tf: -------------------------------------------------------------------------------- 1 | # Do not change the values here, but rather place them in secret.tfvars (gitignored) or in another tfvars file to pass to Terraform 2 | 3 | variable "aws_access_key" { 4 | description = "A valid AWS ACCESS KEY" 5 | type = "string" 6 | } 7 | 8 | variable "aws_secret_key" { 9 | description = "A valid AWS SECRET KEY" 10 | type = "string" 11 | } 12 | 13 | variable "aws_account" { 14 | description = "Your AWS Account number" 15 | type = "string" 16 | } 17 | 18 | variable "aws_region" { 19 | type = "string" 20 | default = "us-east-1" 21 | } 22 | 23 | variable "private_key_name" { 24 | description = "Name of the EC2 private key to use to provision the instances in that region." 25 | type = "string" 26 | } 27 | 28 | variable "private_key_path" { 29 | description = "Path to the private key registred to EC2 keypair with the name put in private_key_name" 30 | type = "string" 31 | } 32 | 33 | variable "admin_public_ips" { 34 | description = "List of public IPs to grant access to the EC2 instances" 35 | type = "list" 36 | default = [ 37 | "0.0.0.0/0" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2019 Sébastien Portebois 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ec2_simple_nokey/ec2.tf: -------------------------------------------------------------------------------- 1 | # --- Some instance to run our services onto 2 | 3 | resource "aws_instance" "ssh_test_demo" { 4 | 5 | ami = "${lookup(var.aws_ami, var.aws_region)}" 6 | availability_zone = "${lookup(var.aws_availability_zone, var.aws_region)}" 7 | 8 | # Check http://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html for the ami ids for each region 9 | # If we really want to handle multiple regions, this should come from a Map 10 | instance_type = "t2.micro" 11 | 12 | iam_instance_profile = "${aws_iam_instance_profile.ssh_test_demo.name}" 13 | 14 | security_groups = ["${aws_security_group.ssh_test_demo.name}"] 15 | 16 | # Default key for ec2 user ssh access 17 | key_name = "${var.private_key_name}" 18 | 19 | user_data = "${file("resources/instance_user_data.sh")}" 20 | 21 | tags { 22 | Name = "ssh_test_demo" 23 | } 24 | } 25 | 26 | 27 | # --- Define some output to easily get the public IP 28 | 29 | output "ec2_instance_public_dns" { 30 | value = "${aws_instance.ssh_test_demo.public_dns}" 31 | } 32 | output "ec2_instance_public_ip" { 33 | value = "${aws_instance.ssh_test_demo.public_ip}" 34 | } 35 | -------------------------------------------------------------------------------- /ec2_vpc/variables.tf: -------------------------------------------------------------------------------- 1 | # Do not change the values here, but rather place them in secret.tfvars (gitignored) or in another tfvars file to pass to Terraform 2 | 3 | variable "aws_access_key" { 4 | description = "A valid AWS ACCESS KEY" 5 | type = "string" 6 | } 7 | 8 | variable "aws_secret_key" { 9 | description = "A valid AWS SECRET KEY" 10 | type = "string" 11 | } 12 | 13 | variable "aws_account" { 14 | description = "Your AWS Account number" 15 | type = "string" 16 | } 17 | 18 | variable "aws_region" { 19 | type = "string" 20 | default = "us-east-1" 21 | } 22 | 23 | variable "private_key_name" { 24 | description = "Name of the EC2 private key to use to provision the instances in that region." 25 | type = "string" 26 | } 27 | 28 | variable "private_key_path" { 29 | description = "Path to the private key registred to EC2 keypair with the name put in private_key_name" 30 | type = "string" 31 | } 32 | 33 | variable "admin_public_ips" { 34 | description = "List of public IPs to grant access to the EC2 instances" 35 | type = "list" 36 | default = [ 37 | "0.0.0.0/0" 38 | ] 39 | /* 40 | Sample white-list: 41 | default = ["75.98.128.74/32"] 42 | */ 43 | } 44 | -------------------------------------------------------------------------------- /ec2_vpc_nokey/ec2.tf: -------------------------------------------------------------------------------- 1 | # --- Some instance to run our services onto 2 | 3 | resource "aws_instance" "ssh_test_demo" { 4 | 5 | ami = "${lookup(var.aws_ami, var.aws_region)}" 6 | availability_zone = "${lookup(var.aws_availability_zone, var.aws_region)}" 7 | # Check http://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html for the ami ids for each region 8 | # If we really want to handle multiple regions, this should come from a Map 9 | instance_type = "t2.micro" 10 | 11 | iam_instance_profile = "${aws_iam_instance_profile.ssh_test_demo.name}" 12 | 13 | vpc_security_group_ids = ["${aws_security_group.ssh_test_demo.id}"] 14 | subnet_id = "${aws_subnet.subnet1-public.id}" 15 | associate_public_ip_address = true 16 | 17 | # Default key for ec2 user ssh access 18 | key_name = "${var.private_key_name}" 19 | 20 | user_data = "${file("resources/instance_user_data.sh")}" 21 | 22 | tags { 23 | Name = "ssh_test_demo" 24 | } 25 | } 26 | 27 | 28 | # --- Define some output to easily get the public IP if we want to ssh into the instances 29 | 30 | output "ec2_instance_public_dns" { 31 | value = "${aws_instance.ssh_test_demo.public_dns}" 32 | } 33 | output "ec2_instance_public_ip" { 34 | value = "${aws_instance.ssh_test_demo.public_ip}" 35 | } 36 | -------------------------------------------------------------------------------- /ec2_simple/resources/iam_role_policy.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "AllowGetAWSUserNames", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "iam:ListUsers" 9 | ], 10 | "Resource": [ 11 | "*" 12 | ] 13 | }, 14 | { 15 | "Sid": "AllowFetchAWSUserSSHKeys", 16 | "Effect": "Allow", 17 | "Action": [ 18 | "iam:ListSSHPublicKeys", 19 | "iam:GetSSHPublicKey" 20 | ], 21 | "Resource": "arn:aws:iam::${aws_account}:user/*" 22 | }, 23 | { 24 | "Sid": "PolicyForECSInstances", 25 | "Effect": "Allow", 26 | "Action": [ 27 | "ecs:CreateCluster", 28 | "ecs:DeregisterContainerInstance", 29 | "ecs:DiscoverPollEndpoint", 30 | "ecs:Poll", 31 | "ecs:RegisterContainerInstance", 32 | "ecs:StartTelemetrySession", 33 | "ecs:Submit*", 34 | "ecr:GetAuthorizationToken", 35 | "ecr:BatchCheckLayerAvailability", 36 | "ecr:GetDownloadUrlForLayer", 37 | "ecr:BatchGetImage", 38 | "ecs:StartTask", 39 | "logs:CreateLogGroup", 40 | "logs:CreateLogStream", 41 | "logs:DescribeLogStreams", 42 | "logs:PutLogEvents" 43 | ], 44 | "Resource": "*" 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /ec2_vpc/resources/iam_role_policy.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "AllowGetAWSUserNames", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "iam:ListUsers" 9 | ], 10 | "Resource": [ 11 | "*" 12 | ] 13 | }, 14 | { 15 | "Sid": "AllowFetchAWSUserSSHKeys", 16 | "Effect": "Allow", 17 | "Action": [ 18 | "iam:ListSSHPublicKeys", 19 | "iam:GetSSHPublicKey" 20 | ], 21 | "Resource": "arn:aws:iam::${aws_account}:user/*" 22 | }, 23 | { 24 | "Sid": "PolicyForECSInstances", 25 | "Effect": "Allow", 26 | "Action": [ 27 | "ecs:CreateCluster", 28 | "ecs:DeregisterContainerInstance", 29 | "ecs:DiscoverPollEndpoint", 30 | "ecs:Poll", 31 | "ecs:RegisterContainerInstance", 32 | "ecs:StartTelemetrySession", 33 | "ecs:Submit*", 34 | "ecr:GetAuthorizationToken", 35 | "ecr:BatchCheckLayerAvailability", 36 | "ecr:GetDownloadUrlForLayer", 37 | "ecr:BatchGetImage", 38 | "ecs:StartTask", 39 | "logs:CreateLogGroup", 40 | "logs:CreateLogStream", 41 | "logs:DescribeLogStreams", 42 | "logs:PutLogEvents" 43 | ], 44 | "Resource": "*" 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /ec2_vpc_nokey/resources/iam_role_policy.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "AllowGetAWSUserNames", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "iam:ListUsers" 9 | ], 10 | "Resource": [ 11 | "*" 12 | ] 13 | }, 14 | { 15 | "Sid": "AllowFetchAWSUserSSHKeys", 16 | "Effect": "Allow", 17 | "Action": [ 18 | "iam:ListSSHPublicKeys", 19 | "iam:GetSSHPublicKey" 20 | ], 21 | "Resource": "arn:aws:iam::${aws_account}:user/*" 22 | }, 23 | { 24 | "Sid": "PolicyForECSInstances", 25 | "Effect": "Allow", 26 | "Action": [ 27 | "ecs:CreateCluster", 28 | "ecs:DeregisterContainerInstance", 29 | "ecs:DiscoverPollEndpoint", 30 | "ecs:Poll", 31 | "ecs:RegisterContainerInstance", 32 | "ecs:StartTelemetrySession", 33 | "ecs:Submit*", 34 | "ecr:GetAuthorizationToken", 35 | "ecr:BatchCheckLayerAvailability", 36 | "ecr:GetDownloadUrlForLayer", 37 | "ecr:BatchGetImage", 38 | "ecs:StartTask", 39 | "logs:CreateLogGroup", 40 | "logs:CreateLogStream", 41 | "logs:DescribeLogStreams", 42 | "logs:PutLogEvents" 43 | ], 44 | "Resource": "*" 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /ec2_simple_nokey/resources/iam_role_policy.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "AllowGetAWSUserNames", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "iam:ListUsers" 9 | ], 10 | "Resource": [ 11 | "*" 12 | ] 13 | }, 14 | { 15 | "Sid": "AllowFetchAWSUserSSHKeys", 16 | "Effect": "Allow", 17 | "Action": [ 18 | "iam:ListSSHPublicKeys", 19 | "iam:GetSSHPublicKey" 20 | ], 21 | "Resource": "arn:aws:iam::${aws_account}:user/*" 22 | }, 23 | { 24 | "Sid": "PolicyForECSInstances", 25 | "Effect": "Allow", 26 | "Action": [ 27 | "ecs:CreateCluster", 28 | "ecs:DeregisterContainerInstance", 29 | "ecs:DiscoverPollEndpoint", 30 | "ecs:Poll", 31 | "ecs:RegisterContainerInstance", 32 | "ecs:StartTelemetrySession", 33 | "ecs:Submit*", 34 | "ecr:GetAuthorizationToken", 35 | "ecr:BatchCheckLayerAvailability", 36 | "ecr:GetDownloadUrlForLayer", 37 | "ecr:BatchGetImage", 38 | "ecs:StartTask", 39 | "logs:CreateLogGroup", 40 | "logs:CreateLogStream", 41 | "logs:DescribeLogStreams", 42 | "logs:PutLogEvents" 43 | ], 44 | "Resource": "*" 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /ec2_simple/ec2.tf: -------------------------------------------------------------------------------- 1 | # --- Some instance to run our services onto 2 | 3 | resource "aws_instance" "ssh_test_demo" { 4 | 5 | # Check http://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html for the AMI ids for each region 6 | # or check other sample for using an HCL map to only set the region 7 | ami = "ami-55870742" # ECS-optimized AMI for us-east-1 8 | availability_zone = "us-east-1b" 9 | 10 | instance_type = "t2.micro" 11 | 12 | iam_instance_profile = "${aws_iam_instance_profile.ssh_test_demo.name}" 13 | 14 | security_groups = ["${aws_security_group.ssh_test_demo.name}"] 15 | 16 | key_name = "${var.private_key_name}" 17 | 18 | # Connection used by the provisionners below to access the instance 19 | connection { 20 | user = "ec2-user" 21 | private_key = "${file(var.private_key_path)}" 22 | } 23 | 24 | provisioner "remote-exec" { 25 | inline = [ 26 | "mkdir -p /home/ec2-user/tf_files" 27 | ] 28 | } 29 | 30 | # Copy the ssh-updates file to the new instance 31 | provisioner "file" { 32 | source = "files/" 33 | destination = "/home/ec2-user/tf_files" 34 | } 35 | 36 | user_data = <