- provision an S3 bucket to serve the images
- ensure that read access to the bucket is as secured as possible
- provision an IAM user with access to write to the bucket
- store the IAM user's access key and secret securely as ansible variables
- write a playbook to deliver this credential and other settings to a configuration file for use by the backend application (see sample below)
The playbook runs against localhost and deliver the app config to a temp location.
This app config is likely being deployed to a environment outside of AWS (bare metal, Azure, etc). Outside of AWS its recommended to create a REST API as an Amazon S3 proxy in API Gateway secured with by a Lambda authorizer using a JSON Web Token. Inside AWS an EC2 Instance Profile that assumes the IAM role with S3 access is the best approach.
Terraform can write files directly so there is an opportunity to optimize the setup by removing Ansible from the workflow.
One of the most difficult parts of IaC is the lack of a local development environment that results in a large feedback loop. Luckily when working with AWS there is an open source tool called localstack
; a fully functional local AWS cloud stack that runs in Docker.
LocalStack requires specific configuration of the Terraform AWS Provider. Creating separate folders for AWS and LocalStack allows for seamless testing in LocalStack and promotion to AWS. Terraform Providers are defined in their respective folders with each env referencing shared modules.
If the backend is deployed to an instance with a static IP define it as a S3 Bucket Policy Condition.
"Condition": {
"IpAddress": {"aws:SourceIp": "8.8.8.8/32"}
}
Ansible can lookup up secrets stored in AWS Secrets Manager and depending on the infrastructure config, storing secrets there vs Ansible Vault may be better for compatibility with other systems in AWS.
Including support for multiple environments (dev, staging, prod) would be simple by using terraform.workspace
in variable names.
Adding terratest for automated testing ensuring PR's work as expected before getting merged and checkov for static code analysis of Terraform config enforces company/team guidelines and security practices.
- Terraform 0.14.4
The best way to actively switch Terraform versions when moving between projects is tfenv
brew install tfenv
- awslocal
A thin wrapper around the aws command line interface for use with LocalStack. You can install the awslocal command via pip though I prefer pipx
pipx install awscli-local
- Docker
Tested with version 20
- direnv (optional)
An extension for your shell. It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.
Automatically sourcing env vars specific to this repo. This can be skipped but sourcing .envrc manually before running commands will be required.
Before running any commands; from the root dir source local env vars if you haven't installed and configured direnv
source .envrc
Ensuring you're the right directory, running the correct executables, and passing parameters via environment variables or specific command-line is cumbersome. Instead, all commands are automated within a Variant config similar to a Makefile but written in yaml.
To install the latest version of variant:
curl -sL https://raw.githubusercontent.com/variantdev/get/master/get | INSTALL_TO=/usr/local/bin sh
chow localstack
chow terraform-localstack-init
chow terraform-localstack-apply
chow ansible-localstack
Review the following files:
ansible/vars.yml
ansible/app.conf
chow reset
chow terraform-aws-init
chow terraform-aws-apply
chow ansible-aws
Review the following files:
ansible/vars.yml
ansible/app.conf
chow terraform-aws-destroy