Skip to content

binlab/terraform-aws-bastion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Terraform AWS Bastion host based on Docker Bastion

License GitHub tag GitHub release Last Commit GitHub commit activity

languages Count Languages Top Code Size Repo Size

A Bastion host is providing isolation between not safe external world and private VPC for infrastructure. That's what Amazon himself writes about it:

Including bastion hosts in your VPC environment enables you to securely connect to your Linux instances without exposing your environment to the Internet. After you set up your bastion hosts, you can access the other instances in your VPC through Secure Shell (SSH) connections on Linux. Bastion hosts are also configured with security groups to provide fine-grained ingress control. source

Key features:

  • Can be run with low consumption of costs or even just on AWS Free Tier
  • No need additional provisioning tools like Ansible, Chief of Puppet, all based on clear Terraform
  • The module is almost an independent with zero-external resources dependencies except for VPC ID and Subnets Id which Bastion module assigned to
  • Provisioning based on CoreOS ignitions so very fast, declarative and predictable
  • Providing a two-mode of work: with using an SSH demon on the host machine or more secure - with additional isolation by running SSH Bastion in Docker container (most recommended)
  • Possible to upgrade or downgrade a Bastion sshd (SSH Server) version (only when used Bastion SSH Docker version)
  • Can be set custom Docker image and version for SSH (with Docker version only) by default is using this one https://github.com/binlab/docker-bastion
  • Optional generation SSH pair for host, by default (RSA-4096) (not recommended, better to provisioning external SSH public key)
  • Access to Bastion by SSH also can by provisioning Root CA certificate and principals
  • Custom SSH Authorized Principals can be configured for bought modes: Host and Docker. More https://man.openbsd.org/sshd_config#AuthorizedPrincipalsFile
  • Provided assigning external own Root CA for cases when Bastion need secure communicate with internal infrastructure

AWS Permissions

For deploying you need a list of permissions. For beginners might be difficult to set up minimal need permissions, so here the list wildcard for main actions.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BastionProvisioning",
      "Effect": "Allow",
      "Action": [
        "ec2:*"
      ],
      "Resource": "*"
    }
  ]
}

Usage

The module can be deployed with almost default values of variables. For more details of the default values looking here

...

module "bastion" {
  source = "github.com/binlab/terraform-aws-bastion?ref=v0.1.0"

  vpc_id                = vpc.vpc_id
  vpc_subnet_id         = vpc.public_subnets[0]
  ec2_ssh_cidr          = ["0.0.0.0/0"]
  bastion_ssh_cidr      = ["0.0.0.0/0"]
  ec2_ssh_auth_keys     = [file("~/.ssh/id_rsa.pub")]
  bastion_ssh_auth_keys = [file("~/.ssh/id_rsa.pub")]
}

output "ec2_ssh_private_key" {
  value = module.bastion.ec2_ssh_private_key
}

output "bastion_public_ip" {
  value = module.bastion.public_ip
}

output "bastion_public_dns" {
  value = module.bastion.public_dns
}

Then run:

$ terraform init
$ terraform apply

After deploying the process you should see:

...
bastion_public_dns = ec2-12-34-56-78.us-east-1.compute.amazonaws.com
bastion_public_ip = 12.34.56.78
ec2_ssh_private_key =
$

* ec2_ssh_private_key is empty because we defined own key

TODO

  • Add examples of use with different cases
  • Hosted module on Terraform Registry - #11
  • Add validation of input data in variables.tf
  • Add support Fedora CoreOS as announced CoreOS Container Linux will reach its end of life on May 26, 2020 and will no longer receive updates.
  • Replace creating EC2 instances to an autoscaling group
  • Add support of OpenStack (OS) Terraform module
  • Add support of Google Cloud Platform (GCP) Terraform module
  • Add support of Microsoft Azure Terraform module
  • Add support of AliCloud Terraform module
  • Add support of Oracle Cloud (OCI) Terraform module

Limitations

  • Requirements block and versions.tf may not accurately display a real minimum version of providers. A declared versions ware just an installed in the time of development and testing of the module and can give guaranties of working with this or higher version. If you use older versions of modules for some reason and can give some guarantees of working with it, please create an issue for downscaling some version to minimal needed.

Requirements

Name Version
terraform >= 0.12
aws >= 2.53.0
ignition >= 1.2.1
tls >= 2.1.1

Providers

Name Version
aws >= 2.53.0
ignition >= 1.2.1
tls >= 2.1.1

Inputs

Name Description Type Default Required
ami_channel AMI filter for OS channel [stable/edge/beta/etc] string "stable" no
ami_image Specific AMI image ID in current Avalability Zone e.g. [ami-123456]
If provided nodes will be run on it, for cases when image built by
Packer if set it will disable search images by "ami_vendor" and
"ami_channel". Note: Instance OS should support CoreOS Ignition
provisioning
string "" no
ami_vendor AMI filter for OS vendor [coreos/flatcar] string "flatcar" no
associate_public_ip Associate a public IP address with an instance in a VPC in time of
launch
bool true no
availability_zone Index of Availability Zone to deploy, starting from 0.
For example: "us-east-1a"=0, "us-east-1b"=1, "us-east-1c"=2 ...
number 0 no
bastion_ssh_auth_keys List of SSH authorized keys assigned to "bastion" user
By default is ["false"] which means disabled pass external keys and
dont generate
list(string) [] no
bastion_ssh_cidr Allowed CIDRs to connect to a cluster on ALB endpoint list(string)
[
"0.0.0.0/32"
]
no
bastion_ssh_port Bastion SSH port open to the users connect. May be open to the
whole world so try to not use the standard port (22). Changing
this value might request redeploy an instance (need to reconfigure
SSH config)
number 10022 no
ca_ssh_public_keys List of SSH Certificate Authority public keys. Specifies a public
keys of certificate authorities that are trusted to sign
user certificates for authentication. More:
https://man.openbsd.org/sshd_config#TrustedUserCAKeys
list(string) [] no
ca_tls_public_keys List of custom Certificate Authority public keys. Used when need
to connect from Vault to resources with a self-signed certificate
list(string) [] no
cpu_credits The credit option for CPU usage [unlimited/standard] string "standard" no
description Description for Tags in all resources. string "Bastion Tower" no
docker_repo Vault Docker repository URI string "docker://binlab/bastion" no
docker_tag Vault Docker image version tag string "1.2.0" no
ec2_ssh_algorithm The name of the algorithm to use for the key.
Currently-supported values are "RSA" and "ECDSA".
Applying Only if variable "ec2_ssh_auth_keys" not set.
string "RSA" no
ec2_ssh_auth_keys List of SSH authorized keys assigned to "Core" user (sudo user) list(string) [] no
ec2_ssh_cidr List of CIDR/IP which will be allowed to connect to EC2 instances
on SSH port. Generally not needed to use. If need, you can connect
to the instance via bastion Sometimes need just for debugging.
By default disallowed all IPs. Allow it with the caution.
list(string)
[
"0.0.0.0/32"
]
no
ec2_ssh_ecdsa_curve When algorithm is "ECDSA", the name of the elliptic curve to use.
May be any one of "P224", "P256", "P384" or "P521", with "P256" as
the default.
Applying Only if variable "ec2_ssh_auth_keys" not set.
string "P256" no
ec2_ssh_port EC2 instance SSH port. Generally not needed to use. If need, you
can connect to the instance via Bastion itself. Sometimes need
just for debugging.
number 22 no
ec2_ssh_rsa_bits When algorithm is "RSA", the size of the generated RSA key in bits.
Defaults to 4096.
Applying Only if variable "ec2_ssh_auth_keys" not set.
number 4096 no
instance_type Type of instance e.g. [t3.small] string "t3.small" no
monitoring CloudWatch detailed monitoring [true/false] bool false no
prefix Prefix of a tag "Name", can be a namespace.
Format of "Name" tag "--"
string "tf-" no
security_groups List of external Security Groups for assigning to EC2 instances.
Useful for custom configuration with another infrastructure to which
the Bastion connected.
list(string) [] no
ssh_admin_principals List of SSH authorized principals for user "Core" when SSH login
configured via Certificate Authority ("ca_ssh_public_key" is set)
https://man.openbsd.org/sshd_config#AuthorizedPrincipalsFile
list(string)
[
"tower"
]
no
ssh_bastion_principals List of SSH authorized principals for "Bastion" user when SSH login
configured via Certificate Authority ("ca_ssh_public_key" is set)
https://man.openbsd.org/sshd_config#AuthorizedPrincipalsFile
list(string)
[
"bastion"
]
no
ssh_core_principals List of SSH authorized principals for user "Admin" when SSH login
configured via Certificate Authority ("ca_ssh_public_key" is set)
More: https://man.openbsd.org/sshd_config#AuthorizedPrincipalsFile
list(string)
[
"sudo"
]
no
stack Stack name and tag "Name", can be a project name.
Format of "Name" tag "--"
string "binlab" no
tags Map of tags assigned to each or created resources in AWS.
By default, used predefined described map in a file "locals.tf".
Each of them can be overwritten here separately.
map(string) {} no
volume_size Node (Root) volume block device Size (GB) e.g. [8] number 8 no
volume_type Node (Root) volume block Device Type e.g. [gp2] string "gp2" no
vpc_id External VPC ID which Bastion module assigned to string n/a yes
vpc_subnet_id External VPC Subnet ID which Bastion module assigned to string n/a yes

Outputs

Name Description
ec2_ssh_private_key SSH private key which generated by module and its public key
part assigned to each of nodes. Don't recommended do this as
a private key will be kept open and stored in a state file.
Instead of this set variable "ssh_authorized_keys". Please note,
if "ssh_authorized_keys" set "ssh_private_key" return empty output
public_dns Public DNS name associated with an instance by AWS
Can be assigned to a domain name by CNAME record
public_ip Public IP associated with an instance by AWS
Can be assigned to a domain name by "A record"
security_group_id Security Group ID which created within the module
Useful for assigning to other Security Groups as a source