AWS Bootstrap

furyctl aws bootstrap provisioner

8 minute read

AWS Bootstrap

This provisioner deploys a battle-tested VPC configuration with a VPN instance. The provisioner enables the deployment of all these components with a simple yaml file. It provides some excellent features:

  • A VPC fully configured to host a Fury EKS Cluster.
    • Enables the deployment of Internal and External Load Balancers from Kubernetes
    • Enables the auto-scaling feature for Kubernetes workloads.
  • Open/Close ssh access to specific IP Ranges (CIDR)
  • Open/Close ssh access to particular users (public keys gathered from GitHub)
  • Scale the VPN instance (horizontal and vertical)
  • many more…

Configuration

kind: Bootstrap
metadata:
  name: 'nameOfTheProject # Used to identify your resources'
spec:
  networkCIDR: '10.0.0.0/16 # Required. Specific VPC Network CIDR to create'
  publicSubnetsCIDRs:
  - Required
  - 10.0.10.0/24
  - 10.0.20.0/24
  - 10.0.30.0/24
  privateSubnetsCIDRs:
  - Required
  - 10.0.192.0/24
  - 10.0.182.0/24
  - 10.0.172.0/24
  vpn:
    instances: 2
    port: 1194
    instanceType: 't3.micro # This is the default value. Specify any AWS EC2 instance
      type'
    diskSize: 50
    operatorName: 'sighup # This is the default value. SSH User to access the instance'
    dhParamsBits: 2048
    subnetCIDR: '172.16.0.0/16 # Required attribute. Should be different from the
      networkCIDR'
    sshUsers:
    - Required
    - angelbarrera92
    - jnardiello
    operatorCIDRs:
    - 0.0.0.0/0
    - This is the default value
  tags:
    myTag: 'MyValue # Use this tags to annotate all resources. Optional'
provisioner: aws

Important notes

  • Network related configuration can not be easily modifiable. All the network configuration is required. Design your networking configuration properly before execute furyctl bootstrap apply.
  • Some vpn attributes are required; others are optional.
    • Changing any of instanceType, operatorCIDRs or sshUsers can be done without downtime. It can take up to five minutes to apply the configuration.
    • Changing any of port, diskSize, dhParamBits, subnetCIDR or operatorName can be done anytime but it will cause downtime and may require reconfiguration of openvpn client configuration files.
    • instances can be scale to 0 if needed. It will cause downtime. Recommended to spin up at least two instances.

Resources

This provisioner creates and configures:

  • VPC: A new virtual private cloud with the CIDR range configured in the yaml file.
  • Internet Gateway: An internet gateway serves two purposes: to provide a target in your VPC route tables for internet-routable traffic, and to perform network address translation (NAT) for instances that have been assigned public IPv4 addresses.
  • NAT Gateway: Enable instances in a private subnet to connect to the internet or other AWS services, but prevent the internet from initiating a connection with those instances.
  • Subnets: Are subsets of the VPC CIDR block. Configured along with route tables, it creates public-facing and private subnets.
  • EC2 Instance: VPN instance with ubuntu 20.04 as the operating system. It has installed and configured OpenVPN, furyagent and the ssh users synchronizer. It has a dedicated elastic IP attached to the instance so that the IP will remain the same in case of recreation. Also, it has a dedicated security group.
  • S3 Bucket: A bucket with the ssh and VPN configuration. It is required to recover the VPN instance in case of a disaster. An IAM user with permissions to read the bucket is created to accomplish these backups/recovery stuff.

Diagram

Requirements

This provisioner requires to have previously configured:

  • AWS Credentials in form of environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_DEFAULT_REGION.
    • Enough IAM permissions to deploy the above resources.
  • A token to use this provisioner as it is an enterprise feature. (Contact sales@sighup.io)
    • Use it by writing --token any time or setting the FURYCTL_TOKEN environment variable.
  • furyctl.
  • furyagent.
  • A configuration file with all the values in place. Please think about it very carefully, some values are inmmutable.

Example execution

In the following lines, you will find an example execution to deploy the bootstrap infrastructure.

First, ensure you pass the requirements. Then create a configuration file with the structure described above.

First, create a new directory:

$ mkdir demo
$ cd demo

Take this bootstrap.yml file as an example. We recommend you to use a non-default backend configuration:

kind: Bootstrap
metadata:
  name: demo
executor:
  version: 0.12.29
provisioner: aws
spec:
  networkCIDR: 10.0.0.0/16
  publicSubnetsCIDRs:  
    - 10.0.1.0/24
    - 10.0.2.0/24
    - 10.0.3.0/24
  privateSubnetsCIDRs: 
    - 10.0.101.0/24
    - 10.0.102.0/24
    - 10.0.103.0/24
  vpn:
    subnetCIDR: 192.168.200.0/24
    sshUsers:
      - angelbarrera92
$ ls
bootstrap.yml

Init the bootstrap project

$ furyctl bootstrap init --token $TOKEN
ERRO[0000] Directory does not exists. stat ./bootstrap: no such file or directory 
INFO[0007] [INFO] running Terraform command: demo/bootstrap/bin/terraform init -no-color -force-copy -input=false -lock-timeout=0s -backend=true -get=true -get-plugins=true -lock=true -upgrade=false -verify-plugins=true -backend-config=configuration/backend.conf 
[AWS] - VPC and VPN

This provisioner creates a battle-tested AWS VPC with all the requirements
set to run a production-grade private EKS cluster.

It creates a VPN server enables deploying the cluster from this computer
once connected to the VPN server.

Then, use furyagent to manage VPN profiles.

[FURYCTL]

Init phase completed.

Project directory: ./bootstrap
Terraform logs: ./bootstrap/logs/terraform.logs

Everything ready to create the infrastructure; execute:

$ furyctl bootstrap apply

Once completed, a new directory bootstrap is available inside the current directory demo.

$ ls
bootstrap   bootstrap.yml

It contains all the terraform project and configuration to properly manage the infrastrucutre.

$ tree bootstrap
bootstrap
├── backend.tf
├── bin
│   └── terraform
├── configuration
│   └── backend.conf
├── logs
│   └── terraform.logs
├── main.tf
├── output
├── output.tf
└── variables.tf

4 directories, 7 files

It didn’t create any infrastructure component; continue the example to deploy it.

Deploy the bootstrap project

$ furyctl bootstrap apply --token $TOKEN
ERRO[0000] Directory already exists                     
WARN[0000] error while updating project subdirectories: Directory already exists 
INFO[0007] [INFO] running Terraform command: demo/bootstrap/bin/terraform init -no-color -force-copy -input=false -lock-timeout=0s -backend=true -get=true -get-plugins=true -lock=true -upgrade=false -verify-plugins=true -backend-config=configuration/backend.conf 
⣾ Re-Initializing terraform project INFO[0008] Updating AWS Bootstrap project               
INFO[0008] [INFO] running Terraform command: demo/bootstrap/bin/terraform apply -no-color -auto-approve -input=false -lock=true -parallelism=10 -refresh=true -var name=demo -var network_cidr=10.0.0.0/16 -var public_subnetwork_cidrs=["10.0.1.0/24","10.0.2.0/24","10.0.3.0/24"] -var private_subnetwork_cidrs=["10.0.101.0/24","10.0.102.0/24","10.0.103.0/24"] -var vpn_subnetwork_cidr=192.168.200.0/24 -var vpn_ssh_users=["angelbarrera92"] 
⣻ Applying terraform project INFO[0155] AWS Updated                                  
INFO[0155] Gathering output file as json                
INFO[0155] [INFO] running Terraform command: demo/bootstrap/bin/terraform output -no-color -json 
INFO[0155] [INFO] running Terraform command: demo/bootstrap/bin/terraform output -no-color -json 
[AWS] - VPC and VPN

All the bootstrap components are up to date.

VPC and VPN ready:

VPC: vpc-0efd097f6e2dd3fcb
Public Subnets: [subnet-02a3 subnet-04d9 subnet-0be0]
Private Subnets: [subnet-0e57 subnet-0fe7 subnet-06e2]

Your VPN instance IP is: 18.193.YYY.ZZZ
Use the ssh sighup username to access the VPN instance with any SSH key configured
for the following GitHub users: [angelbarrera92].

$ ssh sighup@18.193.YYY.ZZZ

Then create a openvpn configuration (ovpn) file using the furyagent cli:

$ furyagent configure openvpn-client --client-name <your-name-goes-here> --config ./bootstrap/furyagent.yml

Discover already registered vpn clients running:

$ furyagent configure openvpn-client --list --config ./bootstrap/furyagent.yml

IMPORTANT! Connect to the VPN with the created ovpn profile to continue deploying
an AWS Kubernetes cluster.

[FURYCTL]
Apply phase completed.

Project directory: ./bootstrap
Terraform logs: ./bootstrap/logs/terraform.logs
Output file: ./bootstrap/output/output.json

Everything is up to date.
Ready to apply or destroy the infrastructure; execute:

$ furyctl bootstrap apply
or
$ furyctl bootstrap destroy

Once completed, everything is ready to start using the VPN instance along with other bootstrap components. In the output message there is enough information to start using the new infrastructure:

VPC: vpc-0efd097f6e2dd3fcb
Public Subnets: [subnet-02a3 subnet-04d9 subnet-0be0]
Private Subnets: [subnet-0e57 subnet-0fe7 subnet-06e2]
Your VPN instance IP is: 18.193.YYY.ZZZ
Use the ssh sighup username to access the VPN instance with any SSH key configured
for the following GitHub users: [angelbarrera92].
$ ssh sighup@18.193.YYY.ZZZ
$ furyagent configure openvpn-client --client-name <your-name-goes-here> --config ./bootstrap/furyagent.yml
$ furyagent configure openvpn-client --list --config ./bootstrap/furyagent.yml

Create an ovpn profile by executing the command above (replace <your-name-goes-here> with your username):

$ furyagent configure openvpn-client --client-name angelbarrera92 --config ./bootstrap/furyagent.yml > angelbarrera92.ovpn
2020-12-18 13:34:58.303002 I | openvpnclient.go:190: Downloading ca.crt, ca.key and ta.key
2020-12-18 13:34:58.341379 I | storage.go:146: Item pki/vpn/ca.crt found [size: 1082]
2020-12-18 13:34:58.341397 I | storage.go:147: Saving item pki/vpn/ca.crt ...
2020-12-18 13:34:58.432603 I | storage.go:146: Item pki/vpn/ca.key found [size: 1675]
2020-12-18 13:34:58.432620 I | storage.go:147: Saving item pki/vpn/ca.key ...
2020-12-18 13:34:58.509569 I | storage.go:146: Item pki/vpn/ta.key found [size: 636]
2020-12-18 13:34:58.509587 I | storage.go:147: Saving item pki/vpn/ta.key ...
2020-12-18 13:34:58.575061 I | openvpnclient.go:195: Creating client cert for:  angelbarrera92
2020-12-18 13:34:58.729849 I | openvpnclient.go:235: Uploading client cert for:  angelbarrera92
$ ls
bootstrap   bootstrap.yml   angelbarrera92.ovpn

Open the profile with your preferred ovpn client, then connect to the VPN.

Modify the configuration

For example, modification of the stack, to allow other ssh users to access the instance (as an example), modify the bootstrap.yml file adding the right GitHub user id (to apply the new public keys in the instance).

kind: Bootstrap
metadata:
  name: demo
executor:
  version: 0.12.29
provisioner: aws
spec:
  networkCIDR: 10.0.0.0/16
  publicSubnetsCIDRs:  
    - 10.0.1.0/24
    - 10.0.2.0/24
    - 10.0.3.0/24
  privateSubnetsCIDRs: 
    - 10.0.101.0/24
    - 10.0.102.0/24
    - 10.0.103.0/24
  vpn:
    subnetCIDR: 192.168.200.0/24
    sshUsers:
      - angelbarrera92
      - ralgozino # New ssh operator

Then run again the furyctl bootstrap apply command.

$ furyctl bootstrap apply --token $TOKEN

The new user can take up to five minutes to be able to access the VPN instance.

Destroy the bootstrap project

If you need to destroy the bootstrap project, first ensure nothing is blocking the destruction of this infrastructure such as EKS clusters or any other component different from the members deployed with this provisioner.

Ensure to disconnect the VPN connection before proceed:

Then run:

$ furyctl bootstrap destroy --token $TOKEN
ERRO[0000] Directory already exists                     
WARN[0000] error while updating project subdirectories: Directory already exists 
INFO[0003] [INFO] running Terraform command: demo/bootstrap/bin/terraform init -no-color -force-copy -input=false -lock-timeout=0s -backend=true -get=true -get-plugins=true -lock=true -upgrade=false -verify-plugins=true -backend-config=configuration/backend.conf 
INFO[0004] Destroying AWS Bootstrap project             
INFO[0004] [INFO] running Terraform command: demo/bootstrap/bin/terraform destroy -no-color -auto-approve -input=false -lock-timeout=0s -lock=true -parallelism=10 -refresh=true -var name=demo -var network_cidr=10.0.0.0/16 -var public_subnetwork_cidrs=["10.0.1.0/24","10.0.2.0/24","10.0.3.0/24"] -var private_subnetwork_cidrs=["10.0.101.0/24","10.0.102.0/24","10.0.103.0/24"] -var vpn_subnetwork_cidr=192.168.200.0/24 -var vpn_ssh_users=["angelbarrera92","ralgozino"] 
⣟ Destroying terraform project INFO[0313] AWS Bootstrap destroyed                      
[AWS] - VPC and VPN
All bootstrap components were destroyed.
VPN and VPC went away.

Had problems, contact us at sales@sighup.io.

[FURYCTL]
Destroy phase completed.

Project directory: ./bootstrap
Terraform logs: ./bootstrap/logs/terraform.logs