Automated deployment of Wordpress related services using Terraform and Ansible
sh -c "$(curl -sSL https://taskfile.dev/install.sh)" -- -d -b $HOME/bin# create terraform/terraform.tfvars
task tfvars
# download providers
task init
# check terraform project correctness
task plan
# deploy
task apply
- DEB822 (from RFC 822) is the new APT norm to declare package repositories on Debian and Ubuntu. Successor to
.list.- it relies on key: value pairs for suites, components, architecture
- every repo has its gpg key
Task runner and build tool : an alternative to Makefile
- uses YAML
- handles cache more efficiently than Makefile : fingerprinting vs date of last modification
- multiplatform
tfvars.sh to check variables and generate terraform.tfvars
A secure Linux distribution
- used as a base layer for Angie
- quickly updated in case of CVE
- compatible with packages compiled for glibc
Declarative APK builder : compiles packages from source code
Image assembler : assembles packages into a distroless image
- secure : images don't have shell, reducing attack surface
- idempotent : images are identical
- lightweight
APKO generates:
- SPDX with all components and licences for each package
- SBOM (software bill of materials) which can be used to audit supply chain
UID and GID are 65532 : conventional ID for non-root
We define a basic network architecture :
- VPC (virtual private cloud) with subnet to isolate the cloud environment
- Internet Gateway to bridge VPC with public internet
- Security group acting as a firewall
Best practices
- Restrict SSH to specific IP
An infrastructure as code tool that defines cloud resources
monoserver
aws_eipElastic IP
=> We choose a monoserver architecture for the sake of simplicity
multi-tier (possible evolution)
- load balancer ALB with public IP
- private subnet EC2 Wordpress with private IP
- private subnet RDS Database with private IP
NB : Ansible gets access to remote machine
- with a bastion instance in a public subnet
- or with AWS Systems Manager Session Manager
| name | description | terraform | AWS |
|---|---|---|---|
| AMI | Pre-configured Amazon Machine Image providing the base Ubuntu OS template. | data.aws_ami |
AWS AMI Docs |
| EC2 Instance | Amazon Elastic Compute Cloud is a virtual compute server hosting the application, containers, and services. | aws_instance |
AWS EC2 Docs |
| KMS Key | Centralized key managenent | aws_kms_key |
AWS KMS |
| EBS Block Store | Persistent cloud storage volume attached to the instance acting as its root hard drive (gp3). |
root_block_device |
AWS EBS Docs |
| Elastic IP (EIP) | Static, persistent public IPv4 address assigned to ensure a fixed endpoint. | aws_eip |
AWS EIP Docs |
| VPC | Virtual Private Cloud : Isolated virtual private network space providing network boundary control. | aws_vpc |
AWS VPC Docs |
| Subnet | A segmented logical partition inside the VPC network to group resources. | aws_subnet |
AWS Subnet Docs |
| Internet Gateway | VPC component enabling bidirectional communication between the network and the public internet. | aws_internet_gateway |
AWS IGW Docs |
| Route Table | Set of routing rules determining where network traffic from the subnets is directed. | aws_route_table |
AWS Route Table Docs |
| Security Group | Virtual stateful firewall controlling permitted inbound and outbound traffic. | aws_security_group |
AWS SG Docs |
| VPC Flow Logs | Feature that captures IP traffic information flowing to and from network interfaces. | aws_flow_log |
AWS Flow Logs Docs |
| CloudWatch Log Group | Centralized log management and storage service repository for system monitoring data. | aws_cloudwatch_log_group |
AWS CloudWatch Logs Docs |
| IAM Role | Identity with specific permission policies determining what AWS resources can do. | aws_iam_role |
AWS IAM Roles Docs |
Some Checkov lints that we fixed:
| code | category | should | should not |
|---|---|---|---|
| CKV_AWS_8 | security | encrypt storage volumes by default | - |
| CKV2_AWS_11 | auditability | capture in/out IP trafic from VPC with a aws_flow_log instance |
- |
| CKV_AWS_12 | networking | default security group should explicitely block by default | - |
| CKV_AWS_23 | observability | description field for rule of security group |
undocumented rules |
| CKV2_AWS_41 | security | instance should use an IAM profile | should not store AWS access keys |
| CKV_AWS_79 | security | metadata should be secured against SSRF with a token => IMDSv2 | no INDSv1 which use classic HTTP GET |
| CKV_AWS_130 | networking | assign private IP by default. Necessity of public IP can be mitigated in different ways (see architecture) | no public IP by default |
| CKV_AWS_135 | performance | instance should have a dedicated bandwidth to EBS volumes | do not share disk traffic with standard network traffic |
| CKV_AWS_158 | security | encrypt logs | - |
| CKV_AWS_382 | networking | outgoing trafic rules should be restricted to necessary protocols | no -1 (all protocols) on 0.0.0.0 |
| CKV2_ANSIBLE_1 | use HTTPS in module calls (ex uri) |
- |
Some others that we ignored:
| code | category | should | should not | tradeoff |
|---|---|---|---|---|
| CKV_AWS_126 | observability | should rely on frequent checks (every 1 mn) | billed by cloud provider |
An agentless configuration management tool
- 3 levels of variables
- group_vars
- vars (within a role)
- default (within a role) : allow to reuse group_vars as they have a lower priority than them, contrary to vars
- a test_sequence can have many steps, among which main ones:
- create
- converge
- verify
- destroy
adapting tests to dockerized test environment
- molecule runs tests in docker container. For
dockerrole, we have distinct tasks whether the environment is prod or test:- in test env, we are within a container with no
systemd. Therefore, we useansible.builtin.shellto look for / launchdockerdprocess - prod relies on
ansible.builtin.servicemodule
- in test env, we are within a container with no
- similarly, test assertion rely on command
docker info
| Role | Responsibilities |
|---|---|
bootstrap |
OS preparation, SSH config, UFW config, create directories for data persistence with appropriate permissions |
docker |
generic role to install daemon and docker compose |
wordpress |
centralized role for stack management : would be too difficult to manage 2 different roles for wordpress and db |
Static analysis for Infra As Code
- compares code against security policies
Reverse proxy. Fork of nginx with extended features
| Url | Kind | Notes |
|---|---|---|
| Terraform doc | π | |
| Ansible doc | π | |
| Taskfile doc | π | |
| Chainguard doc | π | for Melange and Apko |
| Automating IT with Ansible | π | |
| Infra as Code using Terraform | π | |
| Stephane Robert | π | Excellent tutorials |
Resource type
- π official doc
- π course
- ποΈ cheatsheet, synthesis
- π web, article
- π½οΈ video
- fix and improve script
- guide setup with a prompt asking to proofcheck our approach and suggest alternatives with pros and cons -> we remain in charge of choosing the next step
- PR review