Compare commits
No commits in common. "main" and "optional-components" have entirely different histories.
main
...
optional-c
35
.gitignore
vendored
35
.gitignore
vendored
@ -1,35 +0,0 @@
|
||||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
|
||||
# .tfstate files
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
|
||||
# Crash log files
|
||||
crash.log
|
||||
crash.*.log
|
||||
|
||||
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
|
||||
# password, private keys, and other secrets. These should not be part of version
|
||||
# control as they are data points which are potentially sensitive and subject
|
||||
# to change depending on the environment.
|
||||
|
||||
*.tfvars
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
# are not checked in
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
|
||||
# Include override files you do wish to add to version control using negated pattern
|
||||
# !example_override.tf
|
||||
|
||||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||
# example: *tfplan*
|
||||
*tfplan*
|
||||
|
||||
# Ignore CLI configuration files
|
||||
.terraformrc
|
||||
terraform.rc
|
@ -1,7 +0,0 @@
|
||||
formatter: markdown table
|
||||
output:
|
||||
file: README.terraform.md
|
||||
mode: replace
|
||||
sort:
|
||||
by: required
|
||||
|
@ -1 +0,0 @@
|
||||
latest-allowed
|
25
.terraform.lock.hcl
generated
25
.terraform.lock.hcl
generated
@ -1,25 +0,0 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "5.49.0"
|
||||
constraints = "~> 5.49.0"
|
||||
hashes = [
|
||||
"h1:Y3xvYjzBIwYSbcnZDcs6moiy30uxRoY5oT2ExQHKG5A=",
|
||||
"zh:0979b07cdeffb868ea605e4bbc008adc7cccb5f3ba1d3a0b794ea3e8fff20932",
|
||||
"zh:2121a0a048a1d9419df69f3561e524b7e8a6b74ba0f57bd8948799f12b6ad3a1",
|
||||
"zh:573362042ba0bd18e98567a4f45d91b09eb0d223513518ba04f16a646a906403",
|
||||
"zh:57be7a4d6c362be2fa586d270203f4eac1ee239816239a9503b86ebc8fa1fef0",
|
||||
"zh:5c72ed211d9234edd70eac9d77c3cafc7bbf819d1c28332a6d77acf227c9a23c",
|
||||
"zh:7786d1a9781f8e8c0079bf58f4ed4aeddec0caf54ad7ddcf43c47936d545a04f",
|
||||
"zh:82133e7d39787ee91ed41988da71beecc2ecb900b5da94b3f3d77fbc4d4dc722",
|
||||
"zh:8cdb1c154dead85be8352afd30eaf41c59249de9e7e0a8eb4ab8e625b90a4922",
|
||||
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||
"zh:ac215fd1c3bd647ae38868940651b97a53197688daefcd70b3595c84560e5267",
|
||||
"zh:c45db22356d20e431639061a72e07da5201f4937c1df6b9f03f32019facf3905",
|
||||
"zh:c9ba90e62db9a4708ed1a4e094849f88ce9d44c52b49f613b30bb3f7523b8d97",
|
||||
"zh:d2be3607be2209995c80dc1d66086d527de5d470f73509e813254067e8287106",
|
||||
"zh:e3fa20090f3cebf3911fc7ef122bd8c0505e3330ab7d541fa945fea861205007",
|
||||
"zh:ef1b9d5c0b6279323f2ecfc322db8083e141984cfe1bb2f33c0f4934fccb69e3",
|
||||
]
|
||||
}
|
50
README.md
50
README.md
@ -1,50 +0,0 @@
|
||||
# Terraform AWS Pre-base Infrastructure
|
||||
|
||||
## Intro
|
||||
|
||||
This project deploys the basic resources necessary for running multi-user Terraform deployments on an AWS account.
|
||||
|
||||
- an s3 bucket for storing terraform states
|
||||
- a dynamodb table for maintaining terraform locks
|
||||
- an admin user intended for use in other IaC projects
|
||||
- a kms key intended for securing other IaC project secrets
|
||||
- a parameter store tree to keep outputs of this project for reference
|
||||
|
||||
This configuration is intended to be manually executed once at the beginning by the root user.
|
||||
|
||||
| ⚠️ | Re-deploying this project again after running other AWS IaC projects can be <u>*extremely destructive*</u>. |
|
||||
|-|-|
|
||||
|
||||
## Usage
|
||||
|
||||
1. Install [terraform](https://terraform.io). The required version is stated in [`terraform.meta.tf`](./terraform.meta.tf). You can also use [tfenv](https://github.com/tofuutils/tenv) to automatically get a suitable version.
|
||||
|
||||
2. Insert backend config values in `terraform.backend.tfvars`. See [`terraform.backend.remote.tfvars.sample`](./terraform.backend.remote.tfvars.sample) for example, or configure your preferred backend.
|
||||
|
||||
3. *(optional)* Login to terraform cloud to use the remote backend:
|
||||
|
||||
```bash
|
||||
terraform login
|
||||
```
|
||||
|
||||
4. Install terraform dependencies and initiate the backend:
|
||||
|
||||
```bash
|
||||
terraform init -backend-config=terraform.backend.tfvars
|
||||
```
|
||||
|
||||
5. Insert deployment-specific values in `terraform.tfvars`. See [`terraform.tfvars.sample`](./terraform.tfvars.sample) for example.
|
||||
|
||||
6. Then execute as:
|
||||
|
||||
```bash
|
||||
terraform apply -var-file=terraform.tfvars
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- ⚠️ **This project's state file should not be saved in the same AWS account where it is being deployed.**
|
||||
|
||||
- The terraform state is not saved in s3, because it is assumed that no s3 bucket for terraform states exists yet. Instead the [terraform cloud](https://app.terraform.io/) remote backend is used. You may need to setup an account there. Or use local or your preferred backend. You should ensure security of the state file.
|
||||
|
||||
- Generated outputs are also saved in a parameter store tree for future reference.
|
@ -1,69 +0,0 @@
|
||||
<!-- BEGIN_TF_DOCS -->
|
||||
## Requirements
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.8.0 |
|
||||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.49.0 |
|
||||
|
||||
## Providers
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.49.0 |
|
||||
|
||||
## Modules
|
||||
|
||||
No modules.
|
||||
|
||||
## Resources
|
||||
|
||||
| Name | Type |
|
||||
|------|------|
|
||||
| [aws_dynamodb_table.terraform_lock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource |
|
||||
| [aws_iam_access_key.iac](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key) | resource |
|
||||
| [aws_iam_user.iac](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource |
|
||||
| [aws_iam_user_policy_attachment.iac_admin_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource |
|
||||
| [aws_kms_alias.iac](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
|
||||
| [aws_kms_key.iac](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
|
||||
| [aws_s3_bucket.terraform_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
|
||||
| [aws_s3_bucket_lifecycle_configuration.terraform_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource |
|
||||
| [aws_s3_bucket_versioning.terraform_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource |
|
||||
| [aws_ssm_parameter.outputs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource |
|
||||
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
|
||||
| [aws_iam_policy.adminstrator_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source |
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|:--------:|
|
||||
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | aws region where resources will be created | `string` | n/a | yes |
|
||||
| <a name="input_org_name"></a> [org\_name](#input\_org\_name) | organization name; used in various resource identifiers | `string` | n/a | yes |
|
||||
| <a name="input_dynamodb_table_name_slug"></a> [dynamodb\_table\_name\_slug](#input\_dynamodb\_table\_name\_slug) | base name slug of the dynamodb table to create; this prefixed by `var.org_name` | `string` | `"terraform-locks"` | no |
|
||||
| <a name="input_git_project"></a> [git\_project](#input\_git\_project) | git source of this project; used in resource tags | `string` | `""` | no |
|
||||
| <a name="input_iac_username"></a> [iac\_username](#input\_iac\_username) | IAM user to create with admin access; for use by subsequent IaC projects | `string` | `"iac"` | no |
|
||||
| <a name="input_kms_alias"></a> [kms\_alias](#input\_kms\_alias) | alias of the kms key to create | `string` | `"iac"` | no |
|
||||
| <a name="input_parameter_store_path"></a> [parameter\_store\_path](#input\_parameter\_store\_path) | the parameter store path where outputs will be added for reference | `string` | `"/iac/terraform/pre-base/"` | no |
|
||||
| <a name="input_s3_bucket_name_slug"></a> [s3\_bucket\_name\_slug](#input\_s3\_bucket\_name\_slug) | base name slug of the s3 bucket to create; this prefixed by `var.org_name` | `string` | `"terraform-states"` | no |
|
||||
| <a name="input_s3_bucket_use_random_suffix"></a> [s3\_bucket\_use\_random\_suffix](#input\_s3\_bucket\_use\_random\_suffix) | whether to add random suffix to bucket name, or assume the generated name is unique | `bool` | `false` | no |
|
||||
| <a name="input_s3_enable_versioning"></a> [s3\_enable\_versioning](#input\_s3\_enable\_versioning) | whether to enable object versioning on the created bucket | `bool` | `true` | no |
|
||||
| <a name="input_s3_version_limit"></a> [s3\_version\_limit](#input\_s3\_version\_limit) | how many noncurrent versions of s3 objects to retain; max 100 | `number` | `100` | no |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| <a name="output_aws_account_id"></a> [aws\_account\_id](#output\_aws\_account\_id) | n/a |
|
||||
| <a name="output_dynamodb_table_arn"></a> [dynamodb\_table\_arn](#output\_dynamodb\_table\_arn) | n/a |
|
||||
| <a name="output_dynamodb_table_name"></a> [dynamodb\_table\_name](#output\_dynamodb\_table\_name) | n/a |
|
||||
| <a name="output_iam_user_access_key_id"></a> [iam\_user\_access\_key\_id](#output\_iam\_user\_access\_key\_id) | n/a |
|
||||
| <a name="output_iam_user_access_key_secret"></a> [iam\_user\_access\_key\_secret](#output\_iam\_user\_access\_key\_secret) | n/a |
|
||||
| <a name="output_iam_user_arn"></a> [iam\_user\_arn](#output\_iam\_user\_arn) | n/a |
|
||||
| <a name="output_iam_user_name"></a> [iam\_user\_name](#output\_iam\_user\_name) | n/a |
|
||||
| <a name="output_kms_key_alias"></a> [kms\_key\_alias](#output\_kms\_key\_alias) | n/a |
|
||||
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | n/a |
|
||||
| <a name="output_kms_key_id"></a> [kms\_key\_id](#output\_kms\_key\_id) | n/a |
|
||||
| <a name="output_org_name"></a> [org\_name](#output\_org\_name) | n/a |
|
||||
| <a name="output_s3_bucket_name"></a> [s3\_bucket\_name](#output\_s3\_bucket\_name) | n/a |
|
||||
| <a name="output_ssm_parameter_store_path"></a> [ssm\_parameter\_store\_path](#output\_ssm\_parameter\_store\_path) | n/a |
|
||||
<!-- END_TF_DOCS -->
|
@ -1 +0,0 @@
|
||||
data "aws_caller_identity" "current" {}
|
@ -1,13 +0,0 @@
|
||||
resource "aws_dynamodb_table" "terraform_lock" {
|
||||
name = "${var.org_name}-${var.dynamodb_table_name_slug}"
|
||||
hash_key = "LockID"
|
||||
billing_mode = "PAY_PER_REQUEST"
|
||||
# read_capacity = 1
|
||||
# write_capacity = 1
|
||||
# capacities are not relevant on on-demand/PAY_PER_REQUEST billing mode
|
||||
# capacities are very low since terraform apply shouldn't see heavy use
|
||||
attribute {
|
||||
name = "LockID"
|
||||
type = "S"
|
||||
}
|
||||
}
|
16
aws.iam.tf
16
aws.iam.tf
@ -1,16 +0,0 @@
|
||||
data "aws_iam_policy" "adminstrator_access" {
|
||||
name = "AdministratorAccess"
|
||||
}
|
||||
|
||||
resource "aws_iam_user" "iac" {
|
||||
name = var.iac_username
|
||||
}
|
||||
|
||||
resource "aws_iam_user_policy_attachment" "iac_admin_policy" {
|
||||
policy_arn = data.aws_iam_policy.adminstrator_access.arn
|
||||
user = aws_iam_user.iac.name
|
||||
}
|
||||
|
||||
resource "aws_iam_access_key" "iac" {
|
||||
user = aws_iam_user.iac.name
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
resource "aws_kms_key" "iac" {
|
||||
description = "IaC secrets encryption key"
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "iac" {
|
||||
target_key_id = aws_kms_key.iac.key_id
|
||||
name = "alias/${var.kms_alias}"
|
||||
}
|
63
aws.s3.tf
63
aws.s3.tf
@ -1,63 +0,0 @@
|
||||
resource "aws_s3_bucket" "terraform_state" {
|
||||
bucket_prefix = var.s3_bucket_use_random_suffix ? "${var.org_name}-${var.s3_bucket_name_slug}" : null
|
||||
bucket = !var.s3_bucket_use_random_suffix ? "${var.org_name}-${var.s3_bucket_name_slug}" : null
|
||||
force_destroy = false
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_versioning" "terraform_state" {
|
||||
bucket = aws_s3_bucket.terraform_state.id
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_lifecycle_configuration" "terraform_state" {
|
||||
bucket = aws_s3_bucket.terraform_state.id
|
||||
|
||||
rule {
|
||||
id = "general-cleanup"
|
||||
status = "Enabled"
|
||||
filter {
|
||||
prefix = ""
|
||||
}
|
||||
abort_incomplete_multipart_upload {
|
||||
days_after_initiation = 7
|
||||
}
|
||||
expiration {
|
||||
expired_object_delete_marker = true
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "rule" {
|
||||
for_each = var.s3_enable_versioning ? [1] : []
|
||||
content {
|
||||
id = "versions-transition"
|
||||
status = "Enabled"
|
||||
filter {
|
||||
and {
|
||||
prefix = ""
|
||||
object_size_greater_than = 128 * 1024
|
||||
}
|
||||
}
|
||||
noncurrent_version_transition {
|
||||
noncurrent_days = 30
|
||||
storage_class = "STANDARD_IA"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "rule" {
|
||||
for_each = var.s3_enable_versioning ? [1] : []
|
||||
content {
|
||||
id = "versions-expiration"
|
||||
status = "Enabled"
|
||||
filter {
|
||||
prefix = ""
|
||||
}
|
||||
noncurrent_version_expiration {
|
||||
noncurrent_days = 60
|
||||
newer_noncurrent_versions = var.s3_version_limit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
aws.ssm.tf
21
aws.ssm.tf
@ -1,21 +0,0 @@
|
||||
resource "aws_ssm_parameter" "outputs" {
|
||||
for_each = local.parameter_store_outputs
|
||||
|
||||
name = "${trimsuffix(var.parameter_store_path, "/")}/${each.key}"
|
||||
type = try(each.value.secure, false) ? "SecureString" : "String"
|
||||
value = each.value.value
|
||||
}
|
||||
|
||||
locals {
|
||||
parameter_store_outputs = {
|
||||
s3_bucket_name = { value = aws_s3_bucket.terraform_state.id }
|
||||
dynamodb_table_arn = { value = aws_dynamodb_table.terraform_lock.arn }
|
||||
iam_user_name = { value = aws_iam_user.iac.name }
|
||||
iam_user_arn = { value = aws_iam_user.iac.arn }
|
||||
iam_user_access_key_id = { value = aws_iam_access_key.iac.id }
|
||||
iam_user_access_key_secret = { secure = true, value = nonsensitive(aws_iam_access_key.iac.secret) }
|
||||
kms_key_alias = { value = aws_kms_alias.iac.name }
|
||||
kms_key_id = { value = aws_kms_key.iac.key_id }
|
||||
kms_key_arn = { value = aws_kms_key.iac.arn }
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#vim:ft=hcl
|
||||
organization = "bdeshi.space"
|
||||
workspaces {
|
||||
name = "aws-prod-pre-base"
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
terraform {
|
||||
required_version = "~> 1.8.0"
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.49.0"
|
||||
}
|
||||
}
|
||||
backend "remote" {}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
default_tags {
|
||||
tags = {
|
||||
"ManagedBy" = "iac/terraform"
|
||||
"iac/environment" = "global"
|
||||
"iac/component" = "pre-base"
|
||||
"iac/source" = "${trimsuffix(var.git_project, "/")}"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
output "org_name" {
|
||||
value = var.org_name
|
||||
}
|
||||
|
||||
output "aws_account_id" {
|
||||
value = data.aws_caller_identity.current.account_id
|
||||
}
|
||||
|
||||
output "ssm_parameter_store_path" {
|
||||
value = "${trimsuffix(var.parameter_store_path, "/")}/"
|
||||
}
|
||||
|
||||
output "s3_bucket_name" {
|
||||
value = aws_s3_bucket.terraform_state.id
|
||||
}
|
||||
|
||||
output "dynamodb_table_name" {
|
||||
value = aws_dynamodb_table.terraform_lock.id
|
||||
}
|
||||
|
||||
output "dynamodb_table_arn" {
|
||||
value = aws_dynamodb_table.terraform_lock.arn
|
||||
}
|
||||
|
||||
output "iam_user_arn" {
|
||||
value = aws_iam_user.iac.arn
|
||||
}
|
||||
|
||||
output "iam_user_name" {
|
||||
value = aws_iam_user.iac.name
|
||||
}
|
||||
|
||||
output "iam_user_access_key_id" {
|
||||
value = aws_iam_access_key.iac.id
|
||||
}
|
||||
|
||||
output "iam_user_access_key_secret" {
|
||||
value = nonsensitive(aws_iam_access_key.iac.secret)
|
||||
}
|
||||
|
||||
output "kms_key_arn" {
|
||||
value = aws_kms_key.iac.arn
|
||||
}
|
||||
|
||||
output "kms_key_id" {
|
||||
value = aws_kms_key.iac.key_id
|
||||
}
|
||||
|
||||
output "kms_key_alias" {
|
||||
value = aws_kms_alias.iac.name
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
#vim:ft=hcl
|
||||
org_name = "bdeshi.space"
|
||||
aws_region = "us-east-1"
|
||||
git_project = "git@git.bdeshi.space:bdeshi/terraform-aws-pre-base.git"
|
@ -1,67 +0,0 @@
|
||||
variable "org_name" {
|
||||
type = string
|
||||
description = "organization name; used in various resource identifiers"
|
||||
}
|
||||
|
||||
variable "git_project" {
|
||||
type = string
|
||||
description = "git source of this project; used in resource tags"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "aws_region" {
|
||||
type = string
|
||||
description = "aws region where resources will be created"
|
||||
}
|
||||
|
||||
variable "iac_username" {
|
||||
type = string
|
||||
description = "IAM user to create with admin access; for use by subsequent IaC projects"
|
||||
default = "iac"
|
||||
}
|
||||
|
||||
variable "kms_alias" {
|
||||
type = string
|
||||
description = "alias of the kms key to create"
|
||||
default = "iac"
|
||||
}
|
||||
|
||||
variable "s3_bucket_name_slug" {
|
||||
type = string
|
||||
description = "base name slug of the s3 bucket to create; this prefixed by `var.org_name`"
|
||||
default = "terraform-states"
|
||||
}
|
||||
|
||||
variable "dynamodb_table_name_slug" {
|
||||
type = string
|
||||
description = "base name slug of the dynamodb table to create; this prefixed by `var.org_name`"
|
||||
default = "terraform-locks"
|
||||
}
|
||||
|
||||
variable "s3_bucket_use_random_suffix" {
|
||||
type = bool
|
||||
description = "whether to add random suffix to bucket name, or assume the generated name is unique"
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "s3_enable_versioning" {
|
||||
type = bool
|
||||
description = "whether to enable object versioning on the created bucket"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "s3_version_limit" {
|
||||
type = number
|
||||
description = "how many noncurrent versions of s3 objects to retain; max 100"
|
||||
default = 100
|
||||
validation {
|
||||
condition = 0 <= var.s3_version_limit && var.s3_version_limit <= 100
|
||||
error_message = "S3 noncurrent version limit must be between 0 to 100"
|
||||
}
|
||||
}
|
||||
|
||||
variable "parameter_store_path" {
|
||||
type = string
|
||||
description = "the parameter store path where outputs will be added for reference"
|
||||
default = "/iac/terraform/pre-base/"
|
||||
}
|
Loading…
Reference in New Issue
Block a user