add resources
This commit is contained in:
parent
845c72cc0c
commit
19ebb73fe8
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
# 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
.terraform-version
Normal file
1
.terraform-version
Normal file
@ -0,0 +1 @@
|
||||
1.6.3
|
25
.terraform.lock.hcl
generated
Normal file
25
.terraform.lock.hcl
generated
Normal file
@ -0,0 +1,25 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "5.19.0"
|
||||
constraints = "~> 5.19.0"
|
||||
hashes = [
|
||||
"h1:QUX8nqmzZAlmG1eKzNLWqXUnsnvQ222cB9n/9J2U4Eo=",
|
||||
"zh:03aa0f857c6dfce5f46c9bf3aad45534b9421e68983994b6f9dd9812beaece9c",
|
||||
"zh:0639818c5bf9f9943667f39ec38bb945c9786983025dff407390133fa1ca5041",
|
||||
"zh:0b82ad42ced8fb4a138eaf2fd37cf6059ca0bb482114b35fb84f22fc1500324a",
|
||||
"zh:173e8c19a9f1d8f6457c80f4a73a92f420a81d650fc4ad0f97a5dc4b9485bba8",
|
||||
"zh:42913a40ddfe9b4f3c78ad2e3cdc1dcfd48151bc132dc6b49fc32cd6da79db21",
|
||||
"zh:452db5caca2e53d5f7090979d518e77aa5fd98385514b11ee2ce76a46e89cb53",
|
||||
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||
"zh:a12377ade89ee18d9be116436e411e8396898bd70b21ab027c161c785e86238d",
|
||||
"zh:aa9e4746ba49044ad5b4dda57fcdba7bc16fe65f696766fb2c55c30a27abf844",
|
||||
"zh:adfaee76d283f1c321fad2e4154be88d57da8c2ecfdca9516c8920bd2ece36ed",
|
||||
"zh:bf6fbc6d60661c03ed2214173c1deced908dc62480dd41e67ac399fa4abd7467",
|
||||
"zh:cb685da03ad00d1a27891f3d366d75e8795ac81f1b427888b434e6832ca40633",
|
||||
"zh:e0432c78dfaf2baebe2bf5c0ad8087f547c69c2c5a00e4c1dcd5a6344ce726df",
|
||||
"zh:e0ec9ccb8d34d6d0d8bf7f8628c223951832b4d50ea8887fc711fa854b3a28b4",
|
||||
"zh:f274397ada4ef3c1dce2f70e719c8ccf19fc4e7a2e3f45d018764c6267fd7157",
|
||||
]
|
||||
}
|
40
README.md
Normal file
40
README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Terraform AWS Pre-Base
|
||||
|
||||
## 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) or [opentofu](https://opentofu.org/) (preferably with [tfenv](https://github.com/tfutils/tfenv)). The required version is stated in `terraform.meta.tf`.
|
||||
|
||||
2. Install terraform dependencies:
|
||||
|
||||
```bash
|
||||
terraform init -upgrade
|
||||
```
|
||||
|
||||
3. Insert org-specific variable values in `<org-name>.tfvars`. See `*.tfvars.sample` for example.
|
||||
|
||||
4. Then execute as:
|
||||
|
||||
```bash
|
||||
terraform apply -var-file=<org-name>.tfvars
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
The terraform state is not saved in s3, because it is assumed that no s3 bucket for terraform states exists yet. User should secure the state file using some other method.
|
||||
|
||||
Generated outputs are saved in a parameter store tree for future reference.
|
69
README.terraform.md
Normal file
69
README.terraform.md
Normal file
@ -0,0 +1,69 @@
|
||||
<!-- BEGIN_TF_DOCS -->
|
||||
## Requirements
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.6.0 |
|
||||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.19.0 |
|
||||
|
||||
## Providers
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.19.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_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_org_name"></a> [org\_name](#input\_org\_name) | organization name; used in various resource identifiers | `string` | n/a | yes |
|
||||
| <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_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_use_name_suffix"></a> [s3\_use\_name\_suffix](#input\_s3\_use\_name\_suffix) | whether to add random suffix to bucket name, or assume the generated name is unique | `bool` | `false` | 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
aws.data.tf
Normal file
1
aws.data.tf
Normal file
@ -0,0 +1 @@
|
||||
data "aws_caller_identity" "current" {}
|
13
aws.dynamodb.tf
Normal file
13
aws.dynamodb.tf
Normal file
@ -0,0 +1,13 @@
|
||||
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
Normal file
16
aws.iam.tf
Normal file
@ -0,0 +1,16 @@
|
||||
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
|
||||
}
|
8
aws.kms.tf
Normal file
8
aws.kms.tf
Normal file
@ -0,0 +1,8 @@
|
||||
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
Normal file
63
aws.s3.tf
Normal file
@ -0,0 +1,63 @@
|
||||
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
Normal file
21
aws.ssm.tf
Normal file
@ -0,0 +1,21 @@
|
||||
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 }
|
||||
}
|
||||
}
|
21
terraform.meta.tf
Normal file
21
terraform.meta.tf
Normal file
@ -0,0 +1,21 @@
|
||||
terraform {
|
||||
required_version = "~> 1.6.0"
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.19.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, "/")}"
|
||||
}
|
||||
}
|
||||
}
|
51
terraform.outputs.tf
Normal file
51
terraform.outputs.tf
Normal file
@ -0,0 +1,51 @@
|
||||
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
|
||||
}
|
3
terraform.tfvars.sample
Normal file
3
terraform.tfvars.sample
Normal file
@ -0,0 +1,3 @@
|
||||
org_name = "bdeshi.space"
|
||||
aws_region = "us-east-1"
|
||||
git_project = "git@git.bdeshi.space:bdeshi/terraform-aws-pre-base.git"
|
67
terraform.variables.tf
Normal file
67
terraform.variables.tf
Normal file
@ -0,0 +1,67 @@
|
||||
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