π οΈ DevSecOps for Multi-Cloud π₯οΈΒΆ
Cloud DevSecOps using Docker, Terraform, and Multi-Cloud π
π― The CloudOps/GitOps Platform utilizes HashiCorp's Terraform Infrastructure as Code (IaC) on the AWS Cloud π₯οΈ, offering speed, scalability, agility, and cost efficiency. β‘
1. AWS-Terraform DevContainerΒΆ
This DevContainer provides a pre-configured development VSCode Dev-Container environment based on Ubuntu 24.04 LTS with essential DevOps & CloudOps Tools. It simplifies building and testing cloud-native applications for hybrid-cloud platforms (AWS, Azure) by providing comprehensive set of tools for infrastructure automation, container orchestration, Kubernetes management, CI/CD pipelines, and cloud-native application development, including Terraform, Kubernetes, AWS CLI, Azure CLI, and more.
Key Features: Ubuntu Docker, K8s & CI/CD, Python | Node | Go
- Ubuntu 24.04 LTS (Noble): A stable and secure base image optimized for long-term support and compatibility with modern cloud-native tools.
- DevOps toolchain: Pre-installed with tools like awscli, azure-cli,
terraform
,kubectl
,helm
, and more for seamless hybrid-cloud development.- Docker-in-Docker support: Enables containerized development and testing within isolated environments.
- Kubernetes-ready: Includes Minikube | Kind |
k3s, K8s tools: Kubectl, Helm, and other lightweight Kubernetes tools for local testing and development microservices such as K9s. - CI/CD tools: Integrated with tools like
terraform
,tfsec
,act
, andtflint
to enable automated pipelines and code quality checks.
- Python, Node.js, Go support: Pre-installed with interpreters and runtime environments for cross-language development and multi-service applications.
1.1. PrerequisitesΒΆ
Prerequisites: Docker and VSCode
Before using this development environment, ensure you have Docker and VSCode installed on your local machine.
- Docker Desktop - The fastest way to containerize applications.
- VisualStudio Code - Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.
- VSCode Remote Development Extension Pack - An extension pack that lets you open any folder in a container, on a remote machine, or in WSL and take advantage of VS Code's full feature set.
1.2. Getting StartedΒΆ
Reopen in Container
in VSCode
-
Clone the repository: Clone the repository that includes the
devcontainer.json
and theDockerfile
for this setup. On a terminal, inside your Terraform project, execute the following on Mac, Linux or WSL: -
Open in VSCode: Open the repository in VSCode.
-
Build the Dev Container or Reopen in Container: * VSCode will automatically detect the
devcontainer.json
file and prompt you to Reopen in Container. This will automatically build the container based on the providedDockerfile
. * To reopen in container manually, open the command pallete on VS Code and selectRebuild and Reopen in Container
-
Use the pre-configured tools: Once inside the container, all tools like
terraform
,kubectl
, andawscli
are available for use directly from the terminal and ready for use. -
[Advanced] Running Development Services
- Use Docker Compose to spin up services like the API, PostgreSQL, and Elasticsearch locally.
- K3s is used to deploy Kubernetes resources locally.
curl -sL https://raw.githubusercontent.com/1xOps/CloudOps/.dev-container/init-devcontainer.sh | bash
# git clone https://github.com/1xOps/CloudOps
# cd CloudOps/.dev-container
echo "The list of Tools and Utilities to help you build and manage AWS infrastructure with Terraform !!!"
tools.sh
1.3. Taskfile
| Makefile
UsageΒΆ
Taskfile
111
Makefile
For example, if you want to explore the most common terraform commands:To display all available commands:
For more information about each Make targets available.2. AWS-Terraform ModulesΒΆ
-
module
folder: This is the official terraform aws modules which we can use to save our efforts.https://github.com/terraform-aws-modules
- If there is one new/latest module, you can clone/update here. Do a fully testing when update the module.
-
global
folder: It includes all the aws provider information.
3. Tools & UtilitiesΒΆ
The list of pre-installed tools and utilities that are boostrapped to your Multi-Cloud environment
OS UtilitiesΒΆ
- jq = JSON processor
- yq = YAML processor
- envsubst = The envsubst command is used to get a substitute of environment variables and that's what its name suggests.
- bash-completion = Bash completion is a bash function that allows you to auto complete commands or arguments by typing partially commands or arguments, then pressing the [Tab] key.
- aliases (k, kgn, kgp, tfi, tfp, tfy) - type alias to see them
[x] AWS UtilitiesΒΆ
- AWS CLI version 2
- IAM role
[x] Terraform and Related ToolsΒΆ
| Apply | Tool | Description | Language | Advantages | Disadvantages |
|-------|---------------------------------------------------------|----------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
| [x] | **Terraform** | Infrastructure as Code tool for building, changing, and versioning infrastructure | Go | Widely used, supports multiple providers, strong community support | State management can be complex |
| [x] | **Terraform Commands** | Built-in Terraform commands (e.g., `validate`, `plan`, `apply`) | Go | Essential for managing Terraform configurations, built-in commands | Limited to syntax and execution, not security checks |
| [x] | **Terraform Docs** | Generate documentation from Terraform modules | Go | Automates documentation generation, supports various output formats | Limited to Terraform modules |
| [x] | **Tfsec** | Security scanner for Terraform code | Go | Fast, checks for security best practices, easy to use | Limited to security checks |
| [x] | **Terrascan** | Detects security vulnerabilities and compliance violations | Go | Supports multiple IaC tools, extensive policy library (supports OPA) | Can be slow on large codebases |
| [x] | **TFLint AWS Ruleset** (`tflint-ruleset-aws`) | Linter for Terraform code with AWS-specific rules | Go | Pluggable, supports custom AWS rules, actively maintained | Requires configuration |
| [x] | **TFLint AzureRM Ruleset** (`tflint-ruleset-azurerm`) | Linter for Terraform code with Azure-specific rules | Go | Pluggable, supports custom Azure rules, actively maintained | Requires configuration |
| [x] | **Checkov Terraform Resource Scans** | Static code analysis tool for infrastructure-as-code | Python | Supports multiple IaC tools, checks for security best practices, supports custom checks | Might have false positives/negatives |
| [x] | **Terraform Compliance** (`terraform-compliance`) | Compliance-focused tool for Terraform | Python | Scenario-based tests, easy to read, supports custom compliance checks | Not a comprehensive linter, focused on behavior testing |
Kubernetes UtilitiesΒΆ
kubectl
= The Kubernetes command-line tool, kubectl, allows you to run commands against Kubernetes clusters. You can use kubectl to deploy applications, inspect and manage cluster resources, and view logs.helm
= Helm helps you manage Kubernetes applications β Helm Charts help you define, install, and upgrade even the most complex Kubernetes application.kns
= kns is a very small shellscript that utilizes fzf to switch between Kubernetes namespaces fast.-
kctx
= kubectx is a tool to switch between contexts (clusters) on * kubectl faster. A Kubernetes context is a group of access parameters that define which cluster you're interacting with, which user you're using, and which namespace you're working in. It's helpful if you need to access different clusters for different purposes or if you want to limit your access to certain parts of a cluster. -
c9
= Cloud9 CLI and tools (c9 open file.txt) k9s
= K9s is a terminal based UI to interact with your Kubernetes clusters. The aim of this project is to make it easier to navigate, observe and manage your deployed applications in the wild. K9s continually watches Kubernetes for changes and offers subsequent commands to interact with your observed resources.eks-node-viewer
= eks-node-viewer is a tool for visualizing dynamic node usage within a cluster. It was originally developed as an internal tool at AWS for demonstrating consolidation with Karpenter. It displays the scheduled pod resource requests vs the allocatable capacity on the node. It does not look at the actual pod resource usage.
4. MakefileΒΆ
aws/cfn-lint/install Install AWS CloudFormation Linter
aws/cli/install Install AWS Command Line Interface v2
aws/cli/version Display AWS CLI version
aws/cloudformation/create-change-set Creates a list of changes that will be applied to a stack so that you can review the changes before executing them.
aws/cloudformation/create-change-set-without-parameters Creates a list of changes that will be applied to a stack so that you can review the changes before executing them.
aws/cloudformation/create-folder-structure Create a folder structure for CloudFormation projects
aws/cloudformation/create-parameters Copy a CloudFormation parameters to be used as example
aws/cloudformation/create-project Create a CloudFormation project structure
aws/cloudformation/create/service-linked-role Creates an IAM role that is linked to a specific Amazon Elasticsearch service.
aws/cloudformation/create-stack Creates a stack as specified in the template.
aws/cloudformation/create-stack-without-parameters Creates a stack as specified in the template. (don't pass --parameters flag)
aws/cloudformation/create-template-yaml Copy a CloudFormation template to be used as example
aws/cloudformation/delete-change-set Delete latest change-set created
aws/cloudformation/delete/service-linked-role Deletes an IAM role that is linked to a specific Amazon Web Services service.
aws/cloudformation/delete-stack Delete CloudFormation Stack
aws/cloudformation/describe-stack-events Returns all stack related events for a specified stack in reverse chronological order.
aws/cloudformation/describe-stack Returns the description for the specified stack; if no stack name was specified, then it returns the description for all the stacks created.
aws/cloudformation/detect-stack-drift Detects whether a stack's actual configuration differs, or has drifted , from it's expected configuration, as defined in the stack template and any values specified as template parameters.
aws/cloudformation/estimate-template-cost Returns the estimated monthly cost of a template
aws/cloudformation/execute-change-set Execute latest change-set
aws/cloudformation/hygiene Execute CFN Lint and pre-commit rules
aws/cloudformation/latest-change-set Display latest change-set
aws/codeartifact/login Login into AWS CodeArtifact
aws/ssm/install-plugin Install AWS SSM plugin
aws/ssm/start-session Start session with AWS Systems Manager Session Manager
aws/sso/login Login into AWS account and export credentials to ~/.aws/credentials
aws/sts/get-caller-identity Returns details about the IAM user or role whose credentials are used to call the operation.
checkov/run Run Checkov
checkov/version Display checkov version
doc/build Builds documentation
doc/init Initialize documentation
docker/prune Remove unused images and all stopped containers
docker/remove-containers Remove all Docker containers
docker/remove-images Remove all Docker images
docker/remove-volumes Remove all Docker volumes
git/config/init Initialize git configuration for project
github/actions/init Initialize .github/actions directory
github/issues/init Initialize .github/issues directory
github/pull-request/init Initialize .github/pull-request directory
github/workflows/init Initialize .github/workflows directory
gitignore/init Create .gitignore file
gitignore/install Install gitignore
gitignore/list List all gitignore templates
go/install Install Golang
gomplate/version Display Gomplate version
go/version Display Go version
habits/check Performs checks
habits/init Initialize gitignore, documentation, pre-commit, github workflows, issues and pull-request
habits/install Install Habits dependencies
habits/remove Uninstall Habits
habits/update Update Habits
help/clean Help screen
nodejs/install Install NodeJS
npm/install Install NPM
pre-commit/hooks/install Install pre-commit hooks
pre-commit/init Initialize .pre-commit-config.yaml to working directoy
pre-commit/install Install pre-commit using Pip3
pre-commit/remove Remove .pre-commit-config.yaml
pre-commit/run Execute pre-commit hooks on all files
pre-commit/update Update pre-commit-config.yaml with the latest version
pre-commit/version Display pre-commit version
python/install Install Python 3
python/pip/install Install Python 3 Pip
python/version Display Python & Pip version
python/virtualenv/init Initialize a Python 3 virtualenv in the current directory
python/virtualenv/install Install Python 3 virtualenv
python/virtualenv/remove Remove Python 3 virtualenv in the current directory
terraform/apply Builds or changes infrastructure according to Terraform configuration files in DIR
terraform/clean Remove temporary files and directories
terraform/destroy Destroy Terraform-managed infrastructure.
terraform-docs/build Build doc/terraform-docs.md with Terraform Docs
terraform-docs/version Display Terraform Docs version
terraform/fmt Check if the input is formatted. Exit status will be 0 if all input is properly formatted and non-zero otherwise.
terraform/init/backend Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
terraform/init Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
terraform/install Install Terraform latest version
terraform/plan Generates an execution plan for Terraform
terraform/validate Validate the configuration files in a directory, referring only to the configuration and not accessing any remote services such as remote state, provider APIs, etc.
terraform/version Display Terraform version
terrascan/run Run Terrascan
terrascan/version Display Terrascan version
tflint/init/force Init AWS TFLINT, overwrite current configuration
tflint/init Init AWS TFLINT
tflint/run Run TFLINT
tflint/version Display TFLINT version
tfsec/run Run TFSEC
tfsec/version Display TFSEC version
tfswitch/run Execute tfswitch
tfswitch/version Display tfswitch version
ubuntu/install Install most common packages
ubuntu/update Update and upgrade Ubuntu packages
5. DevBox & TaskfileΒΆ
5.1. Devbox PackagesΒΆ
Apply | Package | Description | Version |
---|---|---|---|
[x] | awscli2 | Official AWS CLI version 2 | latest |
[x] | envsubst | Substitute environment variables in shell format strings | latest |
[x] | gh | GitHub command-line interface | latest |
[x] | go | Go programming language | latest |
[x] | go-task | Task runner / simpler Make alternative written in Go | latest |
[x] | google-cloud-sdk | SDK for Google Cloud Platform | latest |
[x] | gum | Tool for rich shell scripts with minimal code | latest |
[x] | jq | Command-line JSON processor | latest |
[x] | k9s | Kubernetes CLI to manage clusters | latest |
[x] | kind | Kubernetes IN Docker - local clusters using Docker container nodes | latest |
[ ] | kluctl | Deployment tool for Kubernetes using a declarative approach | latest |
[ ] | ko | Build and deploy Go applications on Kubernetes | latest |
[x] | kubectl | Kubernetes command-line tool | latest |
[x] | kubectx | Switch between Kubernetes contexts and namespaces | latest |
[x] | kubernetes-helm | Kubernetes package manager (Helm) | latest |
[x] | kustomize | Customize Kubernetes YAML configurations | latest |
[x] | oras | OCI Registry As Storage CLI | latest |
[x] | nodejs_20 | Node.js JavaScript runtime | latest |
[ ] | poetry | Python dependency management and packaging tool | latest |
[x] | python312 | Python programming language version 3.12 | latest |
[x] | tilt | Control microservices locally during development | latest |
[x] | yq or yq-go | YAML processor (like jq but for YAML files) | latest |
[x] | act | Run GitHub Actions locally | latest |
[x] | kubent | Kubernetes deprecated APIs checker | latest |
[x] | yarn | Fast, reliable, and secure dependency management for JavaScript | latest |
[x] | pulumictl | CLI for Pulumi infrastructure as code platform | latest |
[x] | go | Go programming language | 1.23.* |
[ ] | dotnet-sdk | Microsoft .NET SDK | 6.0.* |
[ ] | gradle_7 | Build automation tool | 7.6 |
[x] | curl | Command-line tool for transferring data with URLs | 8 |
5.2. TaskfileΒΆ
6. AWS-Terraform Best PracticesΒΆ
6.1. Terraform BehaviorΒΆ
aws2-wrap: CAUTION that doing
terraform
with correctprofile
, which points to the correct account and assume-role.
[profile Cloudteam-Admin-123456789012]
sso_start_url = https://d-1234567.awsapps.com/start#/
sso_region = ap-southeast-2
sso_account_id = 123456789012
sso_role_name = Cloudandplatformteam-Admin
6.2. Terraform State fileΒΆ
Organization's accounts have a centralized bucket to keep its state.
terraform {
backend "s3" {
bucket = "aws-terraform-org-state"
key = "terraform-aws/<account_number>/*/terraform.tfstate"
region = "ap-southeast-2"
encrypt = true
}
}
aws-terraform-state <--- S3 bucket in account 335083429030
βββ terraform-aws <--- prefix for terraform-aws, in case there are others, like terraform-pagerduty, etc
βββ management <--- account management
β βββ organization <--- subdirectory of account management
β β βββ terraform.tfstate
β βββ policy
β β βββ terraform.tfstate
β βββ sso
β βββ terraform.tfstate
βββ 335083429030 <--- account 335083429030
... <--- other aws account
aws-admin (management)
S3 bucket - aws-terraform-org-state
.
The prefix is terraform-aws/<account_name>
.
current only Cloudteam-Admin
has permission to write to this bucket.
6.3. Other filesΒΆ
terraform.tf
-- this is where the remote state storage is configured.variables.tf
-- where input variables are declared possibly with defaults.main.tf
-- where the actual terraform resources are configured.outputs.tf
-- where output variables are declared.locals.tf
-- specific variables only applicable to a particular environment (prod
ordev
).
6.4. TerraformΒΆ
- Checkout the repository and change directory into the account
- Run
terraform init
to setup the remote state froms3
, will needaws
credentials. - to get the credential from sso
aws sso login --profile=Cloudandplatformteam-Admin-939936386129
- Edit
.tf
files as needed. - Run
terraform plan
to check what will be changed, possibly save aplan
file to use in the next step. - Run
terraform apply
to actually make the changes, possible use aplan
file to limit the actual changes. - Run
terraform show
orterraform output
to list the useful outputs.
6.5. Terraform NamingΒΆ
- Use _ (underscore) instead of - (dash) in all: resource names, data source names, variable names, outputs.
- Beware that actual cloud resources have many hidden restrictions in their naming conventions. Some cannot contain dashes, some must be camel cased. These conventions refer to Terraform names themselves.
- Only use lowercase letters and numbers.
Resource and data source argumentsΒΆ
-
Do not repeat resource type in resource name (not partially, nor completely):
- Good: resource "aws_route_table" "public" {}
- Bad:
resource "aws_route_table" "public_route_table" {} - Bad:
resource "aws_route_table" "public_aws_route_table" {}
-
Resource name should be named this if there is no more descriptive and general name available, or if resource module creates single resource of this type (eg, there is single resource of type aws_nat_gateway and multiple resources of typeaws_route_table, so aws_nat_gateway should be named this and aws_route_table should have more descriptive names - like private, public, database).
- Always use singular nouns for names.
- Use - inside arguments values and in places where value will be exposed to a human (eg, inside DNS name of RDS instance).
- Include count argument inside resource blocks as the first argument at the top and separate by newline after it. See example.
- Include tags argument, if supported by resource as the last real argument, following by depends_on and lifecycle, if necessary. All of these should be separated by single empty line. See example.
- When using condition in count argument use boolean value, if it makes sense, otherwise use length or other interpolation. See example.
- To make inverted conditions don't introduce another variable unless really necessary, use 1 - boolean value instead. For example, count = "${1 - var.create_public_subnets}"