Create AWS account
Create an AWS account.
Copy the access keys of your root user and add them to your .aws/credentials
file.
Set up provider
terraform {
required_version = "~> 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
profile = "your-named-profile"
region = "eu-west-1"
}
Create state bucket
Use the AWS CLI to create an S3 bucket.
#!/bin/bash
export AWS_PROFILE=my-named-profile
BUCKET_NAME=terraform-state
BUCKET_REGION=eu-west-1
echo Creating bucket
aws s3 mb s3://$BUCKET_NAME --region "$BUCKET_REGION"
echo Enabling versioning
aws s3api put-bucket-versioning --bucket $BUCKET_NAME --versioning-configuration Status=Enabled
echo Enabling encryption
aws s3api put-bucket-encryption --bucket $BUCKET_NAME --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'
echo Making bucket private
aws s3api put-bucket-acl --bucket $BUCKET_NAME --acl private
Echo Finished
Update your backend to use the bucket.
terraform {
backend "s3" {
profile = "your-named-profile"
region = "eu-west-1"
bucket = "terraform-state"
key = "project-key"
}
}
Choose account alias
If you want the URL for your sign-in page to contain your company name (or other friendly identifier) instead of your AWS account ID, you can create an account alias.
resource "aws_iam_account_alias" "alias" {
account_alias = "my-account-alias"
}
# Example sign-in page for account alias
https://my-account-alias.signin.aws.amazon.com/console/
Create console users group
resource "aws_iam_group" "console_group" {
name = "console"
}
Create admin group
resource "aws_iam_group" "admin_group" {
name = "admins"
}
resource "aws_iam_group_policy_attachment" "admin_group_policy" {
group = aws_iam_group.admin_group.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
Set password policy
resource "aws_iam_account_password_policy" "password_policy" {
minimum_password_length = 8
require_lowercase_characters = true
require_numbers = true
require_uppercase_characters = true
require_symbols = true
allow_users_to_change_password = true
}
Enforce MFA
data "aws_caller_identity" "current" {}
module "enforce_mfa" {
source = "terraform-module/enforce-mfa/aws"
version = "0.12.5"
policy_name = "managed-mfa-enforce"
account_id = data.aws_caller_identity.current.id
groups = [aws_iam_group.console_group.name]
manage_own_signing_certificates = true
manage_own_ssh_public_keys = true
manage_own_git_credentials = true
}
Create users
locals {
users = [
{
name : "Bjorn",
groups : [aws_iam_group.console_group.name, aws_iam_group.admin_group.name]
},
{
name : "CI",
groups : [aws_iam_group.admin_group.name]
}
]
}
resource "aws_iam_user" "user" {
for_each = { for user in local.users : user.name => user }
name = each.value.name
}
resource "aws_iam_user_group_membership" "user_group_membership" {
for_each = { for user in local.users : user.name => user }
user = each.value.name
groups = each.value.groups
depends_on = [
aws_iam_user.user
]
}
I then enable console access and create access keys manually via the console. It is possible to do this with Terraform, but it's a bit of a hassle.
Don't forget to set up MFA.
Set up budget alerts
locals {
budget_alert_emails = [
"john@doe.com",
"jane@doe.com"
]
}
resource "aws_budgets_budget" "daily_budget" {
name = "daily-budget"
budget_type = "COST"
limit_amount = "10.0"
limit_unit = "USD"
time_period_start = "2021-01-01_00:00"
time_period_end = "2085-01-01_00:00"
time_unit = "DAILY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = local.budget_alert_emails
}
}
resource "aws_budgets_budget" "monthly_budget" {
name = "monthly-budget"
budget_type = "COST"
limit_amount = "50.0"
limit_unit = "USD"
time_period_end = "2085-01-01_00:00"
time_period_start = "2021-01-01_00:00"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED"
subscriber_email_addresses = local.budget_alert_emails
}
}
Delete root access keys
Revoke the access keys of your root user.
Copy the access keys of your admin user and add them to your .aws/credentials
file.