Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding terraform template configuration for AWS
Browse files Browse the repository at this point in the history
thiagoesteves committed Oct 23, 2024
1 parent 89689db commit 26b0d5f
Showing 13 changed files with 1,013 additions and 0 deletions.
105 changes: 105 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Publish the project on AWS

on:
push:
branches:
- test

jobs:
build:
name: Building a release and version file
runs-on: ubuntu-22.04
outputs:
tag: ${{ steps.save-tag.outputs.tag }}
steps:
- uses: actions/checkout@v4
- name: Setup BEAM
uses: erlef/setup-beam@v1
with:
version-file: .tool-versions
version-type: strict
rebar3-version: '3.24.0'

- name: Capture GITHUB_SHORT_SHA
run: |
GITHUB_SHORT_SHA=$(git rev-parse --short ${{ github.sha }})
echo "GITHUB_SHORT_SHA=${GITHUB_SHORT_SHA}" >> $GITHUB_ENV
- name: Capture and update project mix version
id: save-tag
run: |
GLEAM_VERSION=`grep "version =" gleam.toml | awk -F'"' '{print $2}'`
PROJ_TAG=${GLEAM_VERSION}-${GITHUB_SHORT_SHA}
echo "PROJ_TAG=${PROJ_TAG}" >> $GITHUB_ENV
echo "tag=$PROJ_TAG" >> "$GITHUB_OUTPUT"
echo "Creating the tag: $PROJ_TAG"
- name: Update project gleam version
run: |
sed -i "s/.*version =.*/version = \"${{ env.PROJ_TAG }}\"/" gleam.toml
- name: Install Gleam dependencies
run: gleam deps download

- name: Generate the release files
run: gleam export erlang-shipment

- name: Generate tarball to publish
run: |
cd build
tar -czvf cochito-${{ env.PROJ_TAG }}.tar.gz erlang-shipment
- name: Create Release file version
run: |
echo "{\"version\":\"${{ env.PROJ_TAG }}\",\"hash\":\"${GITHUB_SHA}\"}" | jq > current.json
- name: 'Upload release file artifact'
uses: actions/upload-artifact@v4
with:
name: release-file
path: build/cochito-${{ env.PROJ_TAG }}.tar.gz
retention-days: 5

- name: 'Upload version file artifact'
uses: actions/upload-artifact@v4
with:
name: version-file
path: current.json
retention-days: 5

upload_aws:
name: Upload files to AWS environment
needs: build
runs-on: ubuntu-22.04
env:
VERSION_SHA: ${{ needs.build.outputs.tag }}
permissions:
contents: write
steps:
- name: Download version file artefact
uses: actions/download-artifact@v4
with:
name: version-file

- name: Download release file artefact
uses: actions/download-artifact@v4
with:
name: release-file

- name: Copy a release file to the s3 distribution folder
uses: prewk/s3-cp-action@v2
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws_region: "us-east-1"
source: "cochito-${VERSION_SHA}.tar.gz"
dest: "s3://cochito-${{ secrets.CLOUD_ENV_NAME }}-distribution/dist/cochito/cochito-${VERSION_SHA}.tar.gz"

- name: Copy a version file to the s3 version folder
uses: prewk/s3-cp-action@v2
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws_region: "us-east-1"
source: "current.json"
dest: "s3://cochito-${{ secrets.CLOUD_ENV_NAME }}-distribution/versions/cochito/${{ secrets.CLOUD_ENV_NAME }}/current.json"
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
erlang 26.1.2
gleam 1.5.1
terraform 1.5.6
251 changes: 251 additions & 0 deletions devops/aws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# AWS Deployment for Gleam with Terraform

This guide demonstrates how to deploy DeployEx in Amazon Web Services (AWS) using Terraform to programmatically set up the environment.

## Setup

To begin, ensure the following applications are installed:

* Terraform
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)

### 1. SSH Key Pair

Create an SSH key pair named, e. g. `cochito-web-ec2` by visiting the [AWS Key Pair page](https://sa-east-1.console.aws.amazon.com/ec2/home?region=sa-east-1#KeyPairs:). Save the private key in your local SSH folder (`~/.ssh`). The name `cochito-web-ec2` will be used by this file `devops/terraform/modules/standard-account/variables.tf` within terraform templates.

### 2. Environment Secrets

Ensure you have access to the following secrets for storage in Secrets Manager:

| SECRET NAME | EXAMPLE | SOURCE |
|----------|-------------|------:|
| DEPLOYEX_SECRET_KEY_BASE | 42otsNl...Fpq3dIJ02 | mix phx.gen.secret |
| DEPLOYEX_ERLANG_COOKIE| my-cookie | |
| DEPLOYEX_ADMIN_HASHED_PASSWORD | $2b$12$...3Lu6ys538TW | Bcrypt.hash_pwd_salt("my-pass") |

### 3. Variables Configuration

Rename the file [main_example.tf_](./environments/prod/main_example.tf_) to [main.tf](./environments/prod/main.tf) and verify and configure the variables according to your specific environment. Ensure that you also review and update the [variables file](./modules/standard-account/variables.tf). These variables will be utilized across all Terraform templates to ensure correct setup.

### 4. Provisioning the Environment

Check you have the correct credentials to create/update resources in aws:
```bash
cat ~/.aws/credentials
[default]
aws_access_key_id=access_key_id
aws_secret_access_key=secret_access_key
```

Once the key is configured, proceed with provisioning the environment. Navigate to the `./environments/prod` folder and execute the following commands:

```bash
terraform plan # Check if the templates are configured correctly
terraform apply # Apply the configurations to create the environment
```

Wait for the environment to be created. Once the provisioning is complete, you can check the instance at this [address](https://console.aws.amazon.com/ec2/home).

#### Updating Secret Manager

Navigate to [AWS Secrets Manager](https://console.aws.amazon.com/secretsmanager/listsecrets), locate and update the following secret:

* *__deployex-cochito-prod-secrets__*

Click on the secret, then select "Retrieve Secret Value" and edit the secret by adding the new key/value pairs:

```bash
DEPLOYEX_SECRET_KEY_BASE=xxxxxxxxxx
DEPLOYEX_ERLANG_COOKIE=xxxxxxxxxx
DEPLOYEX_ADMIN_HASHED_PASSWORD=xxxxxxxxxx
```

* *__cochito-stage-otp-tls-ca__*, *__cochito-stage-otp-tls-key__*, *__cochito-stage-otp-tls-crt__*:

Create the TLS certificates for OTP distribution using the [Following script](../../../devops/scripts/tls-distribution-certs), changing the appropriate names and regions inside it.

```bash
make tls-distribution-certs
```

The command will generate three files: `ca.crt`, `deployex.key` and `deployex.crt`. Click in each secret in AWS, then select "Retrieve Secret Value" and edit the secret by adding them as plain text, For guidance, you can refer to this [eaxample](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-ranger-tls-certificates.html).

### 5. EC2 Provisioning (Manual Steps)

When running Terraform for the first time, AWS secrets are not yet created. Consequently, attempts to execute deployex or certificates installation will fail. Once these AWS secrets, including certificates and other sensitive information, are updated, subsequent iterations of Terraform's EC2 destroy/create process will no longer require manual intervention.

For initial installations or updates to deployex, follow these steps:

*__PS__*: make sure you have the pair cochito-web-ec2.pem saved in `~/.ssh/`

```bash
ssh -i "cochito-web-ec2.pem" [email protected]
ubuntu@ip-10-0-1-56:~$
```

After getting access to EC2, you need to grant root permissions:

```bash
ubuntu@ip-10-0-1-56:~$ sudo su
root@ip-10-0-1-56:/home/ubuntu$
```

Since the secrets are already updated, we are going to install them in the appropriate addresses
```bash
./install-otp-certificates.sh

# Installing Certificates env: stage at /usr/local/share/ca-certificates #
Retrieving and saving ......
[OK]
```

Check that the certificates are correctly installed:
```bash
ls /usr/local/share/ca-certificates
ca.crt cochito.crt cochito.key deployex.crt deployex.key
```
If you are updating DeployEx, you may need to update the `deployex.sh` script. This step is not necessary during the initial installation, as the script is already installed by default. To update the script, use the following commands:

```bash
version=0.3.0
rm deployex.sh
wget https://github.com/thiagoesteves/deployex/releases/download/${version}/deployex.sh -P /home/ubuntu
chmod a+x deployex.sh

Run the script to install (or update) deployex:

```bash
root@ip-10-0-1-116:/home/ubuntu# ./deployex.sh --install deployex-config.json
# Removing Deployex #
...
# Clean and create a new directory #
# Start systemd #
# Start new service #
Created symlink /etc/systemd/system/multi-user.target.wants/deployex.service → /etc/systemd/system/deployex.service.
```

If you need to update Deployex, follow these steps to ensure that the configuration file reflects the new version:

```bash
vi deployex-config.json
{
...
"version": "0.3.0-rc15",
"os_target": "ubuntu-22.04",
...
}
```

Once the file is updated, run the update command:
```bash
root@ip-10-0-1-116:/home/ubuntu# ./deployex.sh --update deployex-config.json
```

> [!IMPORTANT]
> Depending on the new version of DeployEx, you may need to update both the `deployex-config.json` file and the `deployex.sh` script

At this point, DeployEx should be running. You can view the logs using the following commands:
```bash
tail -f /var/log/deployex/deployex-stdout.log
tail -f /var/log/deployex/deployex-stderr.log
```

### 6. Monitored App deployment

Once DeployEx is running, you __MUST__ deploy the monitored app. This deployment involves creating the release package and the current version JSON file in the designated storage path.

#### Release Version

The release version file __MUST__ be formatted in JSON and include the following information:

```bash
{
"version": "0.1.0-9cad9cd",
"hash": "9cad9cd3581c69fdd02ff60765e1c7dd4599d84a",
"pre_commands": []
}
```

The JSON file __MUST__ be stored at the following path: `/versions/{monitored_app}/{env}/current.json`

#### Release package

After DeployEx fetches the release file, it will download the release package for installation. The package should be located at: `/dist/{monitored_app}/{monitored_app}-{version}.tar.gz`


#### [CI/CD] Upload files to AWS from Github

Here are some useful resources with suggestions on how to automate the upload of version and release files to your environment using GitHub Actions:

* [Guthub Actions - S3 Downloader/Uploader](https://github.com/marketplace/actions/s3-cp)
* [Calori Webserver Example with AWS](https://github.com/thiagoesteves/calori/tree/main/devops/aws/terraform)

### 7. Setting Up HTTPS Certificates with Let's Encrypt

> [!IMPORTANT]
> Before proceeding, make sure that the DNS is correctly configured to point to the AWS instance.


For HTTPS, you can use free certificates from [Let's encrypt](https://letsencrypt.org/getting-started/). In this example, we'll use [cert bot for ubuntu](https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal) to obtain and configure the certificates:

```bash
sudo su
apt update
apt install snapd
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
```

Before installing the certificate, make a backup of the current Nginx configuration file located at `/etc/nginx/sites-available/default`. Certbot may modify this file, so keeping a local copy ensures you can restore it if needed. Once the backup is created, run the following command:
```bash
certbot --nginx
```

This command will install Certbot and automatically configure Nginx to use the obtained certificates. After Nginx is configured, the certificate paths will be set up and will look something like this:

```bash
vi /etc/nginx/sites-available/default
...
ssl_certificate /etc/letsencrypt/live/cochito.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cochito.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
```

Update your configuration file to include the Let's Encrypt certificate paths. Find the section where it mentions:
```bash
# Add here the letsencrypt paths
```
replace this comment with the actual certificate paths:
```bash
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://deployex;
}
ssl_certificate /etc/letsencrypt/live/cochito.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cochito.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
```
Also, ensure that port 443 is enabled for both servers. For example:
```bash
server {
listen 443 ssl; # managed by Certbot
```
After modifying the configuration file, save the changes and restart Nginx:
```bash
sudo su
vi /etc/nginx/sites-available/default
# modify and save file
systemctl reload nginx
```
> [!NOTE]
> After the changes, It may require a reboot.
60 changes: 60 additions & 0 deletions devops/aws/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

### Terraform ###
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
.terraformrc
terraform.rc

### Terragrunt ###
# terragrunt cache directories
**/.terragrunt-cache/*

# Terragrunt debug output file (when using `--terragrunt-debug` option)
# See: https://terragrunt.gruntwork.io/docs/reference/cli-options/#terragrunt-debug
terragrunt-debug.tfvars.json

### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
2 changes: 2 additions & 0 deletions devops/aws/terraform/environments/prod/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
main.tf
.terraform.lock.hcl
16 changes: 16 additions & 0 deletions devops/aws/terraform/environments/prod/main_example.tf_
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Rename me to main.tf and populated with the corrected values

provider "aws" {
region = "sa-east-1"
allowed_account_ids = ["921999999999"]
}

module "standard_account" {
source = "../../modules/standard-account"
account_name = "prod"
server_dns = "cochito.com"
replicas = "3"
ec2_instance_type = "t2.medium"
deployex_dns = "deployex.cochito.com"
deployex_version = "0.3.0-rc21"
}
191 changes: 191 additions & 0 deletions devops/aws/terraform/modules/standard-account/cloud-config.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#cloud-config
#
# Cloud init template for EC2 cochito instances.
#
# In case you need it, the log of the cloud-init can be found at:
# /var/log/cloud-init-output.log
#
packages:
- unzip
- nginx
- jq

write_files:
- path: /home/ubuntu/install-otp-certificates.sh
owner: root:root
permissions: "0755"
content: |
#!/bin/bash
#
# Script to install certificates
#
echo ""
echo "# Installing Certificates env: ${account_name} at /usr/local/share/ca-certificates #"
echo "Retrieving and saving ......"
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-ca | jq -r .SecretString > /usr/local/share/ca-certificates/ca.crt
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-key | jq -r .SecretString > /usr/local/share/ca-certificates/deployex.key
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-key | jq -r .SecretString > /usr/local/share/ca-certificates/cochito.key
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-crt | jq -r .SecretString > /usr/local/share/ca-certificates/deployex.crt
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-crt | jq -r .SecretString > /usr/local/share/ca-certificates/cochito.crt
echo "[OK]"
- path: /home/ubuntu/deployex-config.json
owner: root:root
permissions: "0644"
content: |
{
"app_name": "cochito",
"app_name": "gleam",
"replicas": ${replicas},
"account_name": "${account_name}",
"deployex_hostname": "${deployex_hostname}",
"release_adapter": "s3",
"release_bucket": "cochito-${account_name}-distribution",
"secrets_adapter": "aws",
"secrets_path": "deployex-cochito-${account_name}-secrets",
"aws_region": "${aws_region}",
"version": "${deployex_version}",
"os_target": "ubuntu-22.04",
"deploy_timeout_rollback_ms": 600000,
"deploy_schedule_interval_ms": 5000,
"env": { }
}
- path: /home/ubuntu/config.json
owner: root:root
permissions: "0644"
content: |
{
"agent": {
"run_as_user": "root"
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/deployex/deployex-stdout.log",
"log_group_name": "${log_group_name}",
"log_stream_name": "{instance_id}-deployex-stdout-log",
"timezone": "UTC",
"timestamp_format": "%H: %M: %S%Y%b%-d"
},
{
"file_path": "/var/log/deployex/deployex-stderr.log",
"log_group_name": "${log_group_name}",
"log_stream_name": "{instance_id}-deployex-stderr-log",
"timezone": "UTC",
"timestamp_format": "%H: %M: %S%Y%b%-d"
},
{
"file_path": "/var/log/cochito/cochito-*-stdout.log",
"log_group_name": "${log_group_name}",
"log_stream_name": "{instance_id}-cochito-stdout-log",
"timezone": "UTC",
"timestamp_format": "%H: %M: %S%Y%b%-d"
},
{
"file_path": "/var/log/cochito/cochito-*-stderr.log",
"log_group_name": "${log_group_name}",
"log_stream_name": "{instance_id}-cochito-stderr-log",
"timezone": "UTC",
"timestamp_format": "%H: %M: %S%Y%b%-d"
}
]
}
}
}
}
- path: /etc/nginx/sites-available/default
owner: root:root
permissions: "0644"
content: |
upstream gleam {
server 127.0.0.1:4000 max_fails=5 fail_timeout=60s;
server 127.0.0.1:4001 max_fails=5 fail_timeout=60s;
server 127.0.0.1:4002 max_fails=5 fail_timeout=60s;
}

upstream deployex {
server 127.0.0.1:5001 max_fails=5 fail_timeout=60s;
}

server {
listen 80;
server_name gleam.deployex.pro deployex.gleam.deployex.pro;
if ($host = gleam.deployex.pro) {
return 301 https://$host$request_uri;
} # managed by Certbot


if ($host = deployex.gleam.deployex.pro) {
return 301 https://$host$request_uri;
} # managed by Certbot

return 404; # managed by Certbot
}

server {
#listen 443 ssl; # managed by Certbot
server_name deployex.gleam.deployex.pro;
client_max_body_size 30M;
location / {
allow all;
# Proxy Headers
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Cluster-Client-Ip $remote_addr;
# The Important Websocket Bits!
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://deployex;
}

# Add here the letsencrypt paths
}

server {
#listen 443 ssl; # managed by Certbot
server_name gleam.deployex.pro;
client_max_body_size 30M;
location / {
allow all;
# Proxy Headers
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Cluster-Client-Ip $remote_addr;
# The Important Websocket Bits!
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://gleam;
}
# Add here the letsencrypt paths
}
runcmd:
- cd /tmp
- curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" "-o" "awscliv2.zip"
- unzip "awscliv2.zip"
- ./aws/install
- ./aws/install --update
- /home/ubuntu/install-otp-certificates.sh
- wget https://github.com/thiagoesteves/deployex/releases/download/${deployex_version}/deployex.sh -P /home/ubuntu
- chmod a+x /home/ubuntu/deployex.sh
- /home/ubuntu/deployex.sh --install /home/ubuntu/deployex-config.json
- wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
- dpkg -i -E ./amazon-cloudwatch-agent.deb
- /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ubuntu/config.json -s
- apt install -y build-essential libssl-dev libgtk-3-dev libncurses5-dev libncursesw5-dev libreadline-dev
- wget https://github.com/erlang/otp/releases/download/OTP-26.1.2/otp_src_26.1.2.tar.gz
- tar -xzf otp_src_26.1.2.tar.gz && cd otp_src_26.1.2 && ./configure && make && make install
- systemctl enable --no-block nginx
- systemctl start --no-block nginx
- reboot
131 changes: 131 additions & 0 deletions devops/aws/terraform/modules/standard-account/ec2.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
data "aws_ami" "ubuntu" {
most_recent = true

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

owners = ["099720109477"] # Canonical
}

resource "aws_security_group" "ec2_security" {
name = "cochito-${var.account_name}-ec2-security-group"
description = "Allow SSH traffic from everywhere"
vpc_id = aws_vpc.custom_vpc.id
}

resource "aws_security_group_rule" "allow_ingress_ssh" {
security_group_id = "${aws_security_group.ec2_security.id}"
type = "ingress"
protocol = "tcp"
from_port = 22
to_port = 22
cidr_blocks = ["0.0.0.0/0"]
}

resource "aws_security_group_rule" "allow_ingress_http" {
security_group_id = "${aws_security_group.ec2_security.id}"
type = "ingress"
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
}

resource "aws_security_group_rule" "allow_ingress_https" {
security_group_id = "${aws_security_group.ec2_security.id}"
type = "ingress"
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
}

resource "aws_security_group_rule" "allow_egress_all" {
security_group_id = "${aws_security_group.ec2_security.id}"
type = "egress"
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}

data "aws_iam_policy_document" "ec2_assume_role" {
statement {
effect = "Allow"

principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}

actions = ["sts:AssumeRole"]
}
}

resource "aws_iam_role" "ec2_iam_role" {
name = "cochito-${var.account_name}-instance-role"
assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

resource "aws_iam_role_policy_attachment" "attach-s3" {
role = aws_iam_role.ec2_iam_role.name
policy_arn = aws_iam_policy.s3_distribution_bucket_policy.arn
}

resource "aws_iam_role_policy_attachment" "attach-secrets" {
role = aws_iam_role.ec2_iam_role.name
policy_arn = aws_iam_policy.cochito_secrets_manager_policy.arn
}

resource "aws_iam_role_policy_attachment" "attach-cloudwatch" {
role = aws_iam_role.ec2_iam_role.name
policy_arn = aws_iam_policy.ec2_cloudwatch_policy.arn
}

resource "aws_iam_instance_profile" "cochito_node" {
name = "cochito-${var.account_name}-ec2-profile"
role = aws_iam_role.ec2_iam_role.name
}

data "cloudinit_config" "server_config" {
gzip = true
base64_encode = true
part {
content_type = "text/cloud-config"
content = templatefile("${path.module}/cloud-config.tpl", {
hostname = "${var.server_dns}"
deployex_hostname = "${var.deployex_dns}"
deployex_version = "${var.deployex_version}"
log_group_name = aws_cloudwatch_log_group.ec2_instance_logs.name
account_name = "${var.account_name}"
aws_region = "${var.aws_region}"
replicas = "${var.replicas}"
})
}
}

resource "aws_instance" "ec2_cochito_instance" {
ami = data.aws_ami.ubuntu.id
instance_type = "${var.ec2_instance_type}"
key_name = "${var.aws_key_name}"
vpc_security_group_ids = [aws_security_group.ec2_security.id]
subnet_id = aws_subnet.public_subnet.id
iam_instance_profile = aws_iam_instance_profile.cochito_node.name
associate_public_ip_address = true
user_data = data.cloudinit_config.server_config.rendered
user_data_replace_on_change = true

tags = {
Name = "cochito-${var.account_name}-instance"
}
lifecycle {
create_before_destroy = true
}
}
26 changes: 26 additions & 0 deletions devops/aws/terraform/modules/standard-account/metrics.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# Logs and metrics
#

resource "aws_cloudwatch_log_group" "ec2_instance_logs" {
name = "cochito-${var.account_name}-ec2-instance-logs"
}

resource "aws_iam_policy" "ec2_cloudwatch_policy" {
name = "cochito-${var.account_name}-ec2-cloudwatch-policy"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"logs:Create*",
"logs:PutLogEvents",
"logs:DescribeLogStreams"
]
Effect = "Allow"
Resource = "arn:aws:logs:*:*:*"
},
]
})
}
57 changes: 57 additions & 0 deletions devops/aws/terraform/modules/standard-account/s3.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#
# S3 definitions
#

variable "s3_folders" {
type = list
description = "S3 folders to create for distribution"
default = ["dist/cochito", "versions/cochito"]
}

resource "aws_s3_bucket" "distribution" {
bucket = "cochito-${var.account_name}-distribution"

tags = {
Name = "Distribution bucket"
}
}

resource "aws_s3_object" "distribution_directory_structure" {
count = "${length(var.s3_folders)}"

bucket = "${aws_s3_bucket.distribution.id}"
acl = "private"
key = "${var.s3_folders[count.index]}/"
content_type = "application/x-directory"
source = "/dev/null"
}

# Grant EC2 instances read access to the central S3 distribution
resource "aws_iam_policy" "s3_distribution_bucket_policy" {
name = "cochito-${var.account_name}-s3-distribution-bucket"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:GetBucketLocation",
"s3:GetBucketVersioning",
"s3:ListBucket"
]
Effect = "Allow"
Resource = "arn:aws:s3:::cochito-${var.account_name}-distribution"
},
{
Action = [
"s3:GetObject",
"s3:GetObjectVersion"
]
Effect = "Allow"
Resource = "arn:aws:s3:::cochito-${var.account_name}-distribution/*"
},
]
})
}


62 changes: 62 additions & 0 deletions devops/aws/terraform/modules/standard-account/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# ATTENTION: The values are expected to be set manually by the DASHBOARD
#
# If it is not running on development, remove the recovery_window_in_days = 0
# from the secrets
#
locals {
secret_tag = {
ManagedManually = true
}
}

resource "aws_secretsmanager_secret" "deployex_secrets" {
name = "deployex-cochito-${var.account_name}-secrets"
description = "All Deployex Secrets"
recovery_window_in_days = 0
tags = local.secret_tag
}

resource "aws_secretsmanager_secret" "cochito_otp_tls_ca" {
name = "cochito-${var.account_name}-otp-tls-ca"
description = "TLS ca certificate for OTP distribution"
recovery_window_in_days = 0
tags = local.secret_tag
}

resource "aws_secretsmanager_secret" "cochito_otp_tls_key" {
name = "cochito-${var.account_name}-otp-tls-key"
description = "TLS key certificate for OTP distribution"
recovery_window_in_days = 0
tags = local.secret_tag
}

resource "aws_secretsmanager_secret" "cochito_otp_tls_crt" {
name = "cochito-${var.account_name}-otp-tls-crt"
description = "TLS key certificate for OTP distribution"
recovery_window_in_days = 0
tags = local.secret_tag
}

# Create an IAM policy to grant access to Secrets Manager
resource "aws_iam_policy" "cochito_secrets_manager_policy" {
name = "cochito-${var.account_name}-secrets-manager-access-policy"
description = "Policy for EC2 to access Secrets Manager"

policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = [
"secretsmanager:GetSecretValue",
],
Effect = "Allow",
Resource = [
aws_secretsmanager_secret.cochito_otp_tls_ca.arn,
aws_secretsmanager_secret.cochito_otp_tls_key.arn,
aws_secretsmanager_secret.cochito_otp_tls_crt.arn,
aws_secretsmanager_secret.deployex_secrets.arn,
],
},
],
})
}
40 changes: 40 additions & 0 deletions devops/aws/terraform/modules/standard-account/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
variable "account_name" {
type = string
nullable = false
}

variable "server_dns" {
type = string
nullable = false
}

variable "deployex_dns" {
type = string
nullable = false
}

variable "replicas" {
type = string
nullable = false
}

# ec2 key pair name
variable "aws_key_name" {
default = "cochito-web-ec2"
}

variable "aws_region" {
description = "The AWS region to use"
default = "us-east-1"
}

variable "deployex_version" {
description = "The default deployex version to install"
nullable = false
}

variable "ec2_instance_type" {
description = "The EC2 instance type"
type = string
nullable = false
}
70 changes: 70 additions & 0 deletions devops/aws/terraform/modules/standard-account/vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#
# Virtual Private Network configuration.
#
# VPC (10.0.0.0/16)

data "aws_availability_zones" "available" {
state = "available"
}

resource "aws_vpc" "custom_vpc" {
enable_dns_hostnames = true
enable_dns_support = true

cidr_block = "10.0.0.0/16"

tags = {
Name = "cochito-${var.account_name}-vpc"
}
}

resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.custom_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = data.aws_availability_zones.available.names[0]

tags = {
Name = "cochito Public Subnet"
}
}

resource "aws_subnet" "private_subnet" {
vpc_id = aws_vpc.custom_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = data.aws_availability_zones.available.names[0]

tags = {
Name = "cochito Private Subnet"
}
}

resource "aws_internet_gateway" "cochito_gateway" {
vpc_id = aws_vpc.custom_vpc.id

tags = {
Name = "Some Internet Gateway"
}
}

resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.custom_vpc.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.cochito_gateway.id
}

route {
ipv6_cidr_block = "::/0"
gateway_id = aws_internet_gateway.cochito_gateway.id
}

tags = {
Name = "Public Route Table"
}
}

resource "aws_route_table_association" "public_1_rt_a" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}

0 comments on commit 26b0d5f

Please sign in to comment.