Contact Us | Stratusphere FinOps | StratusGrid Home | Blog
GitHub: StratusGrid/terraform-account-starter
This is to showcase the use of many of the StratusGrid modules working together using terraform.
It will initiate a fully configured AWS account with config and logging set up in all 4 US regions, with terraform state and cloudtrail in us-east-1
- Enable IAM Billing access while logged in as root under My Account
- Delete the default VPCs in all regions you will be using (at least all regions with config rules...)
- Tag the default RDS DB Security Groups in all regions with your required tags (cli to do so is below)
- Determine if you're enabling centralized logging
- Block S3 Public Access Account Wide - See here
# If multiple environments share an account don't do this, or pick a single env
aws rds add-tags-to-resource --resource-name "arn:aws:rds:us-east-1:<account_number>:secgrp:default" --tags "[{\"Key\": \"Environment\",\"Value\": \"<env>\"},{\"Key\": \"Customer\",\"Value\": \"Shared\"}]" --region us-east-1
aws rds add-tags-to-resource --resource-name "arn:aws:rds:us-east-2:<account_number>:secgrp:default" --tags "[{\"Key\": \"Environment\",\"Value\": \"<env>\"},{\"Key\": \"Customer\",\"Value\": \"Shared\"}]" --region us-east-2
aws rds add-tags-to-resource --resource-name "arn:aws:rds:us-west-1:<account_number>:secgrp:default" --tags "[{\"Key\": \"Environment\",\"Value\": \"<env>\"},{\"Key\": \"Customer\",\"Value\": \"Shared\"}]" --region us-west-1
aws rds add-tags-to-resource --resource-name "arn:aws:rds:us-west-2:<account_number>:secgrp:default" --tags "[{\"Key\": \"Environment\",\"Value\": \"<env>\"},{\"Key\": \"Customer\",\"Value\": \"Shared\"}]" --region us-west-2
This repo is fully configured to allow for centralized logging with S3 and it's controlled via a few variables. To enable centralized logging set the following variables log_archive_retention
, aws_org_id
, s3_destination_bucket_name
, logging_account_id
to the required values and uncomment this block in s3-bucket-logging.tf
.
If the apply file you're doing is for the log archive account these vars should be modified enable_centralized_logging
, log_archive_account
in addition to the prior variables with the proper values set.
Once the repo is applied, please go to SNS in the correct region (Most likely us-east-1) and set the appropriate subscriptions for InfraStructure Alerts and Billing Alerts.
enable_centralized_logging = true
s3_destination_bucket_name = var.s3_destination_bucket_name
iam_role_s3_replication_arn = module.iam_role_s3[0].iam_role_arn
logging_account_id = var.logging_account_id
- All resource names shall use
_
and not-
s - StratusGrid mostly follows the file names outlined here, we use a
providers.tf
file for provider specific information. - StratusGrid mainly uses the AWS provider, and this provider supports provider level tagging. We use that whenever possible, some resources don't explicitly support it so tags need to be checked.
- The old naming standard for common files such as inputs, outputs, providers, etc was to prefix them with a
-
, this is no longer true as it's not POSIX compliant. Our pre-commit hooks will fail with this old standard. - StratusGrid generally follows the TerraForm standards outlined here
This repo has several base requirements
- This repo is based upon the AWS
~> 4.9
provider - The following packages are installed via brew:
tflint
,terrascan
,terraform-docs
,gitleaks
,tfsec
,pre-commit', 'sops
,go
- This assumes SOPs v3.7.2
- If you encounter an error like
declare: -g: invalid option
reference this and install Bash 5 - If you need more tflint plugins, please edit the
.tflint.hcl
file with the instructions from here - It's highly recommend that you follow the Git Pre-Commit Instructions below, these will run in GitHub though they should be ran locally to reduce issues
- By default Terraform docs will always run so our auto generated docs are always up to date
- This repo has been tested with awsume
See the README_SOPs.md for how to use and configure SOPs.
See the pre-commit tfsec documentation here, this includes on how to bypass warnings
Terrascan can't do comment based rule skips for modules, so they must be specific in the .config/terrascan.yaml
file otherwise it will always fail.
Several config options have to be specified in the .pre-commit-config.yaml
as they can't be specified in the terrascan config file due to a lack of support.
Terraform Validate can't be used in the Git Pre-Commit hooks as several resources are generated at run time
A sample template Git Repo with how we should setup client infrastructure, in this case it's the StratusGrid Account Starter Template. More details are available here in confluence.
This repo is self documenting via Terraform Docs, please see the note at the bottom.
The way that this repo is structured is supposed to be an infrastructure starter, as well as a base psuedo code repo.
Each file is generally self contained except where it can't be. All variables are in variables.tf
, all data is in data.tf
, and etc.
This file contains the SG module for billing alert anomalies. If you wish to enable Slack Alerts please edit this file for the Slack SSM Parameters.
This file contains the SG module for configuring AWS Config Recorder, this is only enabled if control_tower_enabled == false
.
This file contains the SG module for configuring AWS Config, this is only enabled if control_tower_enabled == false
.
This data file contains all references for data providers, these are fairly generic.
The file contains the SG module for building our EC2 Instance IAM Role that enables SSM, and CloudWatch Publishing.
This file contains the ECS account settings to enable long ARN formats and Container Insights
This file contains the event bridge rule for if ECS, RDS, EC@, Backups, or DynamoDB don't meed the required tagging, this is only enabled if control_tower_enabled == false
.
This file contains the module for creating GuardDuty notifications Events and Topics. Subscriptions are not configured through the module, so must be manually configured at this time.
This file contains the policy and role for assumption by the CICD pipeline processes in the Tooling account, if it exists. Note that the resources will only be created if the "tooling_account_id" parameter is filled in with a valid AWS account ID.
This file contains the SG module for configuring IAM for cross account trusts, this is only enabled if aws_sso_enabled == false
except for the IAM self service module.
This file contains the resource for the IAM local users
This file contains the SG module for configuring the IAM restricted-admin-role role, this is only enabled if aws_sso_enabled == false
.
This file contains the SG module for configuring the IAM cross-account-role-admin role, this is only enabled if aws_sso_enabled == false
.
This file contains the SG module for configuring the IAM restricted-read-role role, this is only enabled if aws_sso_enabled == false
.
This file contains the IAM policy for centralized logging, this is only enabled if log_archive_account == true && enable_centralized_logging == true
.
This file contains the SG module for CloudWatch to fire an alert to SNS whenever the CPU credit balance runs low.
This file contains the SG module for CloudWatch to fire an alert to SNS whenever the Burst Balance credit balance runs low.
This is the standard Apache 2.0 License as defined here.
All local values that aren't file specific.
The StratusGrid standard for Terraform Outputs.
This file contains the necessary provider(s) and there configurations.
This is the readme file for SOPS and how
It's` this file! I'm always updated via TF Docs!
This contains the SG module for setting up a cloudtrail to an S3 Bucket and an SNS Topic.
This contains the SG module for setting up a logging bucket, it's replicated once for each US based region. This file needs to have parts uncommented if using centralized logging.
This contains the SG module for setting up our TF centralized remote state S3 bucket and KMS Key.
This contains all of the S3 related components for centralized logging.
This contains the SG module for sending service limits to an SNS Topic or to Slack.
This contains the SNS topic for all Infrastructure Alerts.
This file creates all of the required SOPS configuration KMS info for other repos to build off of.
The StratusGrid standard for Terraform remote state management.
Rename this file to state.tf
once you're ready to migrate to the remote state.
The StratusGrid standard for provider/module level tagging.
All variables related to this repo for all facets. One day this should be broken up into each file, maybe maybe not.
This file contains the required Terraform versions, as well as the required providers and their versions.
This section is supposed to outline what the misc configuration files do and what is there purpose
This file auto generates your README.md
file.
This file has all of the configuration options required for Terrascan, this is where you would skip rules to.
This file is our standard for how GitHub branch protection rules should be setup.
This file contains the instructions for Github workflows, in specific this file run pre-commit and will allow the PR to pass or fail. This is a safety check and extras for if pre-commit isn't run locally.
This file is a vscode workspace settings file.
This is your gitignore, and contains a slew of default standards.
This file is the GIT pre-commit file and contains all of it's configuration options
This file is the ignore file for the prettier pre-commit actions. Specific files like our SOPS config files have to be ignored.
Specifies the Python version that the actions/setup-python
in GitHub Actions should use.
This file contains the hashes of the Terraform providers and modules we're using.
This file contains the plugin data for TFLint to run.
Name | Version |
---|---|
terraform | >= 1.3 |
aws | ~> 4.9 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
accounts_list | This is a list of all AWS accounts with access to artifact bucket | list(string) |
[ |
no |
append_name_suffix | String to append to the name_suffix used on object names. This is optional, so start with dash if using like so: -mysuffix. This will result in prefix-objectname-env-mysuffix | string |
"" |
no |
aws_org_id | AWS Org ID | string |
n/a | yes |
aws_sso_enabled | A boolean true/false for if Control Tower is deployed or will be deployed. By default this is true, and setting to true removes functions that are replaced by AWS SSO | bool |
true |
no |
control_tower_enabled | A boolean true/false for if Control Tower is deployed or will be deployed. By default this is true, and setting to true removes functions that are imcompatible with Control Tower defaults/common guardrails | bool |
true |
no |
cost_anomaly_billing_threshold | The amount over the normal billing threshold before alerting | string |
"50" |
no |
cost_anomaly_subscription_email | The subscription email for AWS Cost Anomly Billing Alerts | string |
n/a | yes |
enable_centralized_logging | A boolean true/false to enable centralized logging to a log archive account | bool |
n/a | yes |
env_name | Environment name string to be used for decisions and name generation. Appended to name_suffix to create full_suffix | string |
n/a | yes |
guardduty_notifications_enabled | Toggles GuardDuty notifications. Should only be enabled if GuardDuty is enabled on the account. If GuardDuty is enabled Organization-wide via ControlTower, only enable for the delegated GuardDuty admin account. | bool |
false |
no |
log_archive_account | A boolean true/false for is this is the log archive account in the AWS Organization, as this will control centralized logging | bool |
n/a | yes |
log_archive_retention | How many days to delete centralized logs | number |
365 |
no |
logging_account_id | Centralized Logging Account ID, This will only ever be used when enabling centralized logging | string |
n/a | yes |
name_prefix | String to use as prefix on object names | string |
n/a | yes |
override_name_suffix | String to completely override the name_suffix | string |
"" |
no |
payer_account | A boolean true/false for if this is the payer, as this will control billing alerts | string |
false |
no |
prepend_name_suffix | String to prepend to the name_suffix used on object names. This is optional, so start with dash if using like so: -mysuffix. This will result in prefix-objectname-mysuffix-env | string |
"" |
no |
region | AWS Region to target | string |
n/a | yes |
s3_destination_bucket_name | Destination Bucket Name for S3 Centralized Logging Replication | string |
"" |
no |
s3_replication_iam_role_arn | This is the ARN of the IAM role assumed by the source account which allows writing to the central logging bucket. | string |
"" |
no |
service_limit_email | The subscription email for AWS Service Limits | string |
n/a | yes |
source_repo | URL of the repo which holds this code | string |
n/a | yes |
tooling_account | Indicates if the account currently being affected is the tooling account which runs CICD pipelines. | bool |
false |
no |
tooling_account_id | The account number for the tooling account. Used in IAM policy/role for use by deployment pipelines. | string |
"" |
no |
trusted_users_account_arns | Account which users are provisioned in and should be granted access to cross account roles. Enter like arn:aws:iam::123456789012:root | list(string) |
[] |
no |
Name | Description |
---|---|
account_id | Account which terraform was run on |
common_tags | tags which should be applied to all taggable objects |
ec2_default_instance_arn | The ec2 default instance IAM role that was created ARN |
iam_role_url_restricted_admin | URL to assume restricted admin role in this account |
iam_role_url_restricted_approver | URL to assume restricted approver role in this account |
iam_role_url_restricted_read_only | URL to assume restricted read only role in this account |
log_bucket_ids | ID of logging bucket |
name_prefix | string to prepend to all resource names |
name_suffix | string to append to all resource names |
sops_kms_id | The KMS id you need to use for SOPs related files |
terraform_state_bucket | s3 bucket to store terraform state |
terraform_state_config_s3_key | key to use for terraform state key configuration - this is the s3 object key where the config will be stored |
terraform_state_dynamodb_table | dynamodb table to control terraform locking |
terraform_state_kms_key_arn | kms key to use for encrytption when storing/reading terraform state configuration |
- We assume a basic knowledge of terraform
- We assume StratusGrid written and unwritten (Listen I know, if you find an unwritten standard please standardize and it document it) standards
- We assume you know how to switch TF states to new envs
- We assume that if you find something wrong or have an improvement you will submit a PR and run terraform-docs
- Of all most importance, we assume that you read this or at least skimmed this README file
When doing a first run update the init-tfvars tfvars file for the relevant values produced via the account starter.
After the initial and the terraform state file is created. Rename state.tfnot
to state.tf
and run rm -rf .terraform
. Then rerun the terraform init to migrate the state file to S3.
This is purely an example repo and it's subject to change for each and every client, please use your best judgement. While adhering to StratusGrids' Standards.
#Verify you have bash5
brew install bash
# Test your pre-commit hooks - This will force them to run on all files
pre-commit run --all-files
# Add your pre-commit hooks forever
pre-commit install
terraform init -backend-config=./init-tfvars/dev.tfvars
terraform apply -var-file ./apply-tfvars/dev.tfvars
terraform init -backend-config=./init-tfvars/stg.tfvars
terraform apply -var-file ./apply-tfvars/stg.tfvars
terraform init -backend-config=./init-tfvars/prd.tfvars
terraform apply -var-file ./apply-tfvars/prd.tfvars
Note: Before reading, uncomment the code for the environment that you wish to apply the code to. This goes for both the init-tfvars and apply-tfvars folders.
- Chris Hurst StratusChris
- Ivan Casco ivancasco-sg
- Tyler Martin SGTyler
- Wesley Kirkland wesleykirklandsg
Note, manual changes to the README will be overwritten when the documentation is updated. To update the documentation, run terraform-docs -c .config/.terraform-docs.yml .