├── .devcontainer ├── Dockerfile └── devcontainer.json ├── main.tf ├── .terraform-docs.yml ├── .github └── workflows │ ├── release-please.yml │ └── main.yml ├── examples ├── simple │ ├── outputs.tf │ ├── variables.tf │ └── main.tf └── simple-static-bucket-name │ ├── outputs.tf │ ├── variables.tf │ └── main.tf ├── .pre-commit-config.yaml ├── .editorconfig ├── .chglog ├── config.yml └── CHANGELOG.tpl.md ├── migrations.tf ├── .gitignore ├── .tflint.hcl ├── LICENSE ├── outputs.tf ├── dynamo.tf ├── policy.tf ├── docs └── upgrade-1.0.md ├── bucket.tf ├── CHANGELOG.md ├── replica.tf ├── variables.tf └── README.md /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/devcontainers/base:bullseye 2 | 3 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 4 | && apt-get -y install --no-install-recommends python3-pip \ 5 | && pip install --no-input pre-commit 6 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.1.4" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.3" 8 | 9 | configuration_aliases = [aws.replica] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.terraform-docs.yml: -------------------------------------------------------------------------------- 1 | formatter: "markdown table" 2 | 3 | sections: 4 | show: 5 | - requirements 6 | - providers 7 | - inputs 8 | - outputs 9 | 10 | sort: 11 | enabled: true 12 | by: required 13 | 14 | settings: 15 | default: false 16 | lockfile: false 17 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | name: release-please 6 | jobs: 7 | release-please: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: google-github-actions/release-please-action@v3 11 | with: 12 | release-type: terraform-module 13 | -------------------------------------------------------------------------------- /examples/simple/outputs.tf: -------------------------------------------------------------------------------- 1 | output "kms_key" { 2 | description = "The KMS customer master key to encrypt state buckets." 3 | value = module.remote_state.kms_key.key_id 4 | } 5 | 6 | output "state_bucket" { 7 | description = "The S3 bucket to store the remote state file." 8 | value = module.remote_state.state_bucket.bucket 9 | } 10 | -------------------------------------------------------------------------------- /examples/simple-static-bucket-name/outputs.tf: -------------------------------------------------------------------------------- 1 | output "kms_key" { 2 | description = "The KMS customer master key to encrypt state buckets." 3 | value = module.remote_state.kms_key.key_id 4 | } 5 | 6 | output "state_bucket" { 7 | description = "The S3 bucket to store the remote state file." 8 | value = module.remote_state.state_bucket.bucket 9 | } 10 | -------------------------------------------------------------------------------- /examples/simple/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | description = "The AWS region in which resources are set up." 3 | type = string 4 | default = "us-east-1" 5 | } 6 | 7 | 8 | variable "replica_region" { 9 | description = "The AWS region to which the state bucket is replicated." 10 | type = string 11 | default = "us-west-1" 12 | } 13 | -------------------------------------------------------------------------------- /examples/simple-static-bucket-name/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | description = "The AWS region in which resources are set up." 3 | type = string 4 | default = "us-east-1" 5 | } 6 | 7 | 8 | variable "replica_region" { 9 | description = "The AWS region to which the state bucket is replicated." 10 | type = string 11 | default = "us-west-1" 12 | } 13 | 14 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/antonbabenko/pre-commit-terraform 3 | rev: v1.62.3 4 | hooks: 5 | - id: terraform_fmt 6 | - id: terraform_docs 7 | args: 8 | - --args=--config=.terraform-docs.yml 9 | - id: terraform_tflint 10 | exclude: "test/" 11 | args: 12 | - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 2 9 | indent_style = space 10 | insert_final_newline = true 11 | max_line_length = 80 12 | trim_trailing_whitespace = true 13 | 14 | [*.{tf,tfvars}] 15 | indent_size = 2 16 | indent_style = space 17 | 18 | [*.md] 19 | max_line_length = 0 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Terraform", 3 | "build": { 4 | "dockerfile": "./Dockerfile", 5 | "context": "." 6 | }, 7 | "features": { 8 | "ghcr.io/devcontainers/features/terraform:1": { 9 | "version": "latest", 10 | "installTerraformDocs": true 11 | } 12 | }, 13 | "customizations": { 14 | "vscode": { 15 | "extensions": [ 16 | "EditorConfig.EditorConfig", 17 | "GitHub.copilot" 18 | ] 19 | } 20 | }, 21 | "postCreateCommand": "pre-commit install" 22 | } -------------------------------------------------------------------------------- /.chglog/config.yml: -------------------------------------------------------------------------------- 1 | style: github 2 | template: CHANGELOG.tpl.md 3 | info: 4 | title: CHANGELOG 5 | repository_url: https://github.com/nozaq/terraform-aws-remote-state-s3-backend 6 | options: 7 | commits: 8 | filters: 9 | Type: 10 | - feat 11 | - fix 12 | - perf 13 | - refactor 14 | commit_groups: 15 | # title_maps: 16 | # feat: Features 17 | # fix: Bug Fixes 18 | # perf: Performance Improvements 19 | # refactor: Code Refactoring 20 | header: 21 | pattern: "^(\\w*)\\:\\s(.*)$" 22 | pattern_maps: 23 | - Type 24 | - Subject 25 | notes: 26 | keywords: 27 | - BREAKING CHANGE 28 | -------------------------------------------------------------------------------- /migrations.tf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------------------------- 2 | # Migrations to 0.7.0 3 | # -------------------------------------------------------------------------------------------------- 4 | 5 | moved { 6 | from = aws_kms_key.replica 7 | to = aws_kms_key.replica[0] 8 | } 9 | 10 | moved { 11 | from = aws_s3_bucket.replica 12 | to = aws_s3_bucket.replica[0] 13 | } 14 | 15 | moved { 16 | from = aws_s3_bucket_public_access_block.replica 17 | to = aws_s3_bucket_public_access_block.replica[0] 18 | } 19 | 20 | moved { 21 | from = aws_s3_bucket_policy.replica_force_ssl 22 | to = aws_s3_bucket_policy.replica_force_ssl[0] 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/simple/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.15" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.0.0" 8 | } 9 | } 10 | } 11 | 12 | provider "aws" { 13 | region = var.region 14 | } 15 | 16 | provider "aws" { 17 | alias = "replica" 18 | region = var.replica_region 19 | } 20 | 21 | module "remote_state" { 22 | source = "../../" 23 | 24 | providers = { 25 | aws = aws 26 | aws.replica = aws.replica 27 | } 28 | } 29 | 30 | resource "aws_iam_user" "terraform" { 31 | name = "TerraformUser" 32 | } 33 | 34 | resource "aws_iam_user_policy_attachment" "remote_state_access" { 35 | user = aws_iam_user.terraform.name 36 | policy_arn = module.remote_state.terraform_iam_policy.arn 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | .terraform.lock.hcl 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | *.tfvars 19 | 20 | # Ignore override files as they are usually used to override resources locally and so 21 | # are not checked in 22 | override.tf 23 | override.tf.json 24 | *_override.tf 25 | *_override.tf.json 26 | 27 | # Include override files you do wish to add to version control using negated pattern 28 | # 29 | # !example_override.tf 30 | 31 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 32 | # example: *tfplan* 33 | -------------------------------------------------------------------------------- /.tflint.hcl: -------------------------------------------------------------------------------- 1 | config { 2 | module = false 3 | force = false 4 | disabled_by_default = false 5 | } 6 | 7 | rule "terraform_deprecated_interpolation" { 8 | enabled = true 9 | } 10 | 11 | rule "terraform_deprecated_index" { 12 | enabled = true 13 | } 14 | 15 | rule "terraform_unused_declarations" { 16 | enabled = true 17 | } 18 | 19 | rule "terraform_comment_syntax" { 20 | enabled = true 21 | } 22 | 23 | rule "terraform_documented_outputs" { 24 | enabled = true 25 | } 26 | 27 | rule "terraform_documented_variables" { 28 | enabled = true 29 | } 30 | 31 | rule "terraform_typed_variables" { 32 | enabled = true 33 | } 34 | 35 | rule "terraform_module_pinned_source" { 36 | enabled = true 37 | } 38 | 39 | rule "terraform_required_version" { 40 | enabled = true 41 | } 42 | 43 | rule "terraform_required_providers" { 44 | enabled = true 45 | } 46 | 47 | rule "terraform_standard_module_structure" { 48 | enabled = true 49 | } 50 | 51 | rule "terraform_workspace_remote" { 52 | enabled = true 53 | } 54 | -------------------------------------------------------------------------------- /examples/simple-static-bucket-name/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.15" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.0.0" 8 | } 9 | } 10 | } 11 | 12 | provider "aws" { 13 | region = var.region 14 | } 15 | 16 | provider "aws" { 17 | alias = "replica" 18 | region = var.replica_region 19 | } 20 | 21 | module "remote_state" { 22 | source = "../../" 23 | override_s3_bucket_name = true 24 | s3_bucket_name = "my-fixed-bucket-name-remote-state" 25 | s3_bucket_name_replica = "my-fixed-bucket-replica-name-remote-state" 26 | 27 | providers = { 28 | aws = aws 29 | aws.replica = aws.replica 30 | } 31 | } 32 | 33 | resource "aws_iam_user" "terraform" { 34 | name = "TerraformUser" 35 | } 36 | 37 | resource "aws_iam_user_policy_attachment" "remote_state_access" { 38 | user = aws_iam_user.terraform.name 39 | policy_arn = module.remote_state.terraform_iam_policy.arn 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Takashi Nozawa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "kms_key" { 2 | description = "The KMS customer master key to encrypt state buckets." 3 | value = aws_kms_key.this 4 | } 5 | 6 | output "kms_key_alias" { 7 | description = "The alias of the KMS customer master key used to encrypt state bucket and dynamodb." 8 | value = aws_kms_alias.this 9 | } 10 | 11 | output "state_bucket" { 12 | description = "The S3 bucket to store the remote state file." 13 | value = aws_s3_bucket.state 14 | } 15 | 16 | output "replica_bucket" { 17 | description = "The S3 bucket to replicate the state S3 bucket." 18 | value = try(aws_s3_bucket.replica[0], null) 19 | } 20 | 21 | output "dynamodb_table" { 22 | description = "The DynamoDB table to manage lock states." 23 | value = aws_dynamodb_table.lock 24 | } 25 | 26 | output "kms_key_replica" { 27 | description = "The KMS customer master key to encrypt replica bucket and dynamodb." 28 | value = try(aws_kms_key.replica[0], null) 29 | } 30 | 31 | output "terraform_iam_policy" { 32 | description = "The IAM Policy to access remote state environment." 33 | value = var.terraform_iam_policy_create ? aws_iam_policy.terraform[0] : null 34 | } 35 | -------------------------------------------------------------------------------- /.chglog/CHANGELOG.tpl.md: -------------------------------------------------------------------------------- 1 | {{ if .Versions -}} 2 | 3 | ## [Unreleased] 4 | 5 | {{ if .Unreleased.CommitGroups -}} 6 | {{ range .Unreleased.CommitGroups -}} 7 | ### {{ .Title }} 8 | {{ range .Commits -}} 9 | - {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} 10 | {{ end }} 11 | {{ end -}} 12 | {{ end -}} 13 | {{ end -}} 14 | 15 | {{ range .Versions }} 16 | 17 | ## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} 18 | {{ range .CommitGroups -}} 19 | ### {{ .Title }} 20 | {{ range .Commits -}} 21 | - {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} 22 | {{ end }} 23 | {{ end -}} 24 | 25 | {{- if .NoteGroups -}} 26 | {{ range .NoteGroups -}} 27 | ### {{ .Title }} 28 | {{ range .Notes }} 29 | {{ .Body }} 30 | {{ end }} 31 | {{ end -}} 32 | {{ end -}} 33 | {{ end -}} 34 | 35 | {{- if .Versions }} 36 | [Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD 37 | {{ range .Versions -}} 38 | {{ if .Tag.Previous -}} 39 | [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} 40 | {{ end -}} 41 | {{ end -}} 42 | {{ end -}} 43 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | jobs: 8 | pre-commit-checks: 9 | name: Pre-commit checks 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | - name: Terraform min/max versions 15 | id: minMax 16 | uses: clowdhaus/terraform-min-max@v1.0.4 17 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} 18 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.4.1 19 | with: 20 | terraform-version: ${{ steps.minMax.outputs.maxVersion }} 21 | terraform-docs-version: v0.16.0 22 | validate-examples: 23 | name: Validate examples 24 | runs-on: ubuntu-latest 25 | defaults: 26 | run: 27 | shell: bash 28 | working-directory: examples 29 | steps: 30 | - uses: hashicorp/setup-terraform@v1 31 | - name: Checkout 32 | uses: actions/checkout@v2 33 | - name: Check examples 34 | env: 35 | EXAMPLES: simple 36 | run: | 37 | for EXAMPLE in ${EXAMPLES} 38 | do 39 | echo "Validating $EXAMPLE"... 40 | cd $EXAMPLE && terraform init && terraform validate && cd - 41 | done 42 | -------------------------------------------------------------------------------- /dynamo.tf: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------------------------- 2 | # DynamoDB Table for State Locking 3 | #--------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | # The table must have a primary key named LockID. 7 | # See below for more detail. 8 | # https://www.terraform.io/docs/backends/types/s3.html#dynamodb_table 9 | lock_key_id = "LockID" 10 | } 11 | 12 | resource "aws_dynamodb_table" "lock" { 13 | name = var.dynamodb_table_name 14 | billing_mode = var.dynamodb_table_billing_mode 15 | hash_key = local.lock_key_id 16 | deletion_protection_enabled = var.dynamodb_deletion_protection_enabled 17 | 18 | attribute { 19 | name = local.lock_key_id 20 | type = "S" 21 | } 22 | 23 | server_side_encryption { 24 | enabled = var.dynamodb_enable_server_side_encryption 25 | kms_key_arn = aws_kms_key.this.arn 26 | } 27 | 28 | point_in_time_recovery { 29 | enabled = true 30 | } 31 | 32 | dynamic "replica" { 33 | for_each = var.enable_replication == true ? [1] : [] 34 | content { 35 | region_name = data.aws_region.replica[0].name 36 | kms_key_arn = var.dynamodb_enable_server_side_encryption ? aws_kms_key.replica[0].arn : null 37 | } 38 | } 39 | stream_enabled = var.enable_replication 40 | stream_view_type = var.enable_replication ? "NEW_AND_OLD_IMAGES" : null 41 | 42 | tags = var.tags 43 | } 44 | -------------------------------------------------------------------------------- /policy.tf: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------------------------- 2 | # IAM Policy 3 | # See below for permissions necessary to run Terraform. 4 | # https://www.terraform.io/docs/backends/types/s3.html#example-configuration 5 | # 6 | # terragrunt users would also need additional permissions. 7 | # https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/74 8 | #--------------------------------------------------------------------------------------------------- 9 | 10 | resource "aws_iam_policy" "terraform" { 11 | count = var.terraform_iam_policy_create ? 1 : 0 12 | 13 | name_prefix = var.override_terraform_iam_policy_name ? null : var.terraform_iam_policy_name_prefix 14 | name = var.override_terraform_iam_policy_name ? var.terraform_iam_policy_name : null 15 | policy = < 0 3 | } 4 | 5 | data "aws_region" "state" { 6 | } 7 | 8 | #--------------------------------------------------------------------------------------------------- 9 | # KMS Key to Encrypt S3 Bucket 10 | #--------------------------------------------------------------------------------------------------- 11 | 12 | resource "aws_kms_key" "this" { 13 | description = var.kms_key_description 14 | deletion_window_in_days = var.kms_key_deletion_window_in_days 15 | enable_key_rotation = var.kms_key_enable_key_rotation 16 | 17 | tags = var.tags 18 | } 19 | 20 | resource "aws_kms_alias" "this" { 21 | name = "alias/${var.kms_key_alias}" 22 | target_key_id = aws_kms_key.this.key_id 23 | } 24 | 25 | #--------------------------------------------------------------------------------------------------- 26 | # Bucket Policies 27 | #--------------------------------------------------------------------------------------------------- 28 | 29 | data "aws_iam_policy_document" "state_force_ssl" { 30 | statement { 31 | sid = "AllowSSLRequestsOnly" 32 | actions = ["s3:*"] 33 | effect = "Deny" 34 | resources = [ 35 | aws_s3_bucket.state.arn, 36 | "${aws_s3_bucket.state.arn}/*" 37 | ] 38 | condition { 39 | test = "Bool" 40 | variable = "aws:SecureTransport" 41 | values = ["false"] 42 | } 43 | principals { 44 | type = "*" 45 | identifiers = ["*"] 46 | } 47 | } 48 | } 49 | 50 | #--------------------------------------------------------------------------------------------------- 51 | # Bucket 52 | #--------------------------------------------------------------------------------------------------- 53 | 54 | resource "aws_s3_bucket_policy" "state_force_ssl" { 55 | bucket = aws_s3_bucket.state.id 56 | policy = data.aws_iam_policy_document.state_force_ssl.json 57 | 58 | depends_on = [aws_s3_bucket_public_access_block.state] 59 | } 60 | 61 | resource "aws_s3_bucket" "state" { 62 | bucket_prefix = var.override_s3_bucket_name ? null : var.state_bucket_prefix 63 | bucket = var.override_s3_bucket_name ? var.s3_bucket_name : null 64 | force_destroy = var.s3_bucket_force_destroy 65 | 66 | tags = var.tags 67 | } 68 | 69 | resource "aws_s3_bucket_ownership_controls" "state" { 70 | bucket = aws_s3_bucket.state.id 71 | 72 | rule { 73 | object_ownership = "BucketOwnerPreferred" 74 | } 75 | } 76 | 77 | resource "aws_s3_bucket_acl" "state" { 78 | depends_on = [aws_s3_bucket_ownership_controls.state] 79 | bucket = aws_s3_bucket.state.id 80 | acl = "private" 81 | } 82 | 83 | resource "aws_s3_bucket_versioning" "state" { 84 | bucket = aws_s3_bucket.state.id 85 | 86 | versioning_configuration { 87 | status = "Enabled" 88 | } 89 | } 90 | 91 | resource "aws_s3_bucket_logging" "state" { 92 | count = var.s3_logging_target_bucket != null ? 1 : 0 93 | 94 | bucket = aws_s3_bucket.state.id 95 | target_bucket = var.s3_logging_target_bucket 96 | target_prefix = var.s3_logging_target_prefix 97 | } 98 | 99 | resource "aws_s3_bucket_server_side_encryption_configuration" "state" { 100 | bucket = aws_s3_bucket.state.id 101 | 102 | rule { 103 | apply_server_side_encryption_by_default { 104 | sse_algorithm = "aws:kms" 105 | kms_master_key_id = aws_kms_key.this.arn 106 | } 107 | } 108 | } 109 | 110 | resource "aws_s3_bucket_lifecycle_configuration" "state" { 111 | count = local.define_lifecycle_rule ? 1 : 0 112 | bucket = aws_s3_bucket.state.id 113 | 114 | rule { 115 | id = "auto-archive" 116 | status = "Enabled" 117 | 118 | dynamic "noncurrent_version_transition" { 119 | for_each = var.noncurrent_version_transitions 120 | 121 | content { 122 | noncurrent_days = noncurrent_version_transition.value.days 123 | storage_class = noncurrent_version_transition.value.storage_class 124 | } 125 | } 126 | 127 | dynamic "noncurrent_version_expiration" { 128 | for_each = var.noncurrent_version_expiration != null ? [var.noncurrent_version_expiration] : [] 129 | 130 | content { 131 | noncurrent_days = noncurrent_version_expiration.value.days 132 | } 133 | } 134 | } 135 | } 136 | 137 | resource "aws_s3_bucket_public_access_block" "state" { 138 | bucket = aws_s3_bucket.state.id 139 | block_public_acls = true 140 | block_public_policy = true 141 | ignore_public_acls = true 142 | restrict_public_buckets = true 143 | } 144 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [1.6.1](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.6.0...v1.6.1) (2024-04-20) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * replica replication configuration must wait for versioning to be enabled in both buckets. ([#126](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/126)) ([64bfff6](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/64bfff667a26918c457abe5a671f1903ebe9a983)) 14 | 15 | ## [1.6.0](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.5.0...v1.6.0) (2023-12-21) 16 | 17 | 18 | ### Features 19 | 20 | * add a deletion protection flag for DynamoDB table ([#122](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/122)) ([41ab8a9](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/41ab8a975202fe2df4872f9a5f281d2dc26674f8)) 21 | 22 | ## [1.5.0](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.4.0...v1.5.0) (2023-04-28) 23 | 24 | 25 | ### Features 26 | 27 | * enable ACLs for new S3 buckets after AWS changed defaults ([#111](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/111)) ([42f63c6](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/42f63c6d76ecff16b94eef07c36902b292243c98)) 28 | 29 | 30 | ### Bug Fixes 31 | 32 | * crash when replication is disabled ([#113](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/113)) ([30a9e9f](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/30a9e9f278936d601c69e95fd78d48182e8fd8bf)) 33 | 34 | ## [1.4.0](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.3.3...v1.4.0) (2022-10-22) 35 | 36 | 37 | ### Features 38 | 39 | * validate bucket names ([#102](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/102)) ([f35f913](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/f35f9138ba7345da04e617ef5f3229bc2a18b3a0)) 40 | 41 | ## [1.3.3](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.3.2...v1.3.3) (2022-07-23) 42 | 43 | 44 | ### Bug Fixes 45 | 46 | * kms_key_alias output ([#97](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/97)) ([abc5dc9](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/abc5dc91d947fb20b5759fc06fdad27b8f3327ef)) 47 | 48 | ## [1.3.2](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.3.1...v1.3.2) (2022-07-09) 49 | 50 | 51 | ### Bug Fixes 52 | 53 | * only enable Stream when replication is enabled ([#95](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/95)) ([7b1aafc](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/7b1aafc3381ee92664cf9ab2e6388bc5b2bc53fa)) 54 | 55 | ## [1.3.1](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.3.0...v1.3.1) (2022-07-09) 56 | 57 | 58 | ### Bug Fixes 59 | 60 | * disable Stream for DynamoDB ([#93](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/93)) ([704fb97](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/704fb9713f447535ae88a16c6948eddc6aac6f70)) 61 | 62 | ## [1.3.0](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.2.0...v1.3.0) (2022-07-09) 63 | 64 | 65 | ### Features 66 | 67 | * added the capability to specify an alias for the KMS Key ([#87](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/87)) ([fc70af4](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/fc70af4572c686045c95936e0a1152d089fe749b)) 68 | * allow replication for DDB ([#91](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/91)) ([e63200a](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/e63200a17c78a109c89f81e16eb9566b7aef2009)) 69 | * optionally set the IAM policy boundary ([#90](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/90)) ([bfb3701](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/bfb3701fe1c222b82c77f6e60eb0903105e5b081)) 70 | 71 | 72 | ### Bug Fixes 73 | 74 | * replace output to be either null or the actual value. ([#92](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/92)) ([a8141fd](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/a8141fd78214154dd2480b194d4efab11a233a7c)) 75 | 76 | ## [1.2.0](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.1.2...v1.2.0) (2022-04-16) 77 | 78 | 79 | ### Features 80 | 81 | * use S3 replication rule V2 ([#85](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/85)) ([26e8493](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/26e84939279e277493ca7f0ef087a7be1565312e)) 82 | 83 | ## [1.1.2](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.1.1...v1.1.2) (2022-03-16) 84 | ### Bug Fixes 85 | - updated policy to fix syntax issue ([#80](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/80)) ([bb5e8d9](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/bb5e8d9ca9e8b9993cc7143d6ae8ee963f15f053)) 86 | 87 | ## [1.1.1](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.1.0...v1.1.1) (2022-03-15) 88 | ### Bug Fixes 89 | - add permissions required by terragrunt ([#75](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/75)) ([93f327c](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/93f327ca936bc09d0694145a2374b695256b373b)) 90 | 91 | ## [1.1.0](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/compare/v1.0.1...v1.1.0) (2022-03-08) 92 | ### Features 93 | - enable server side encryption for DynamoDB table ([c1c9262](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/commit/c1c9262064c25d9437a97e7ea8793a4250ee6708)) 94 | 95 | ## 1.0.1 - 2022-03-05 96 | ### Fix 97 | - replication depends on versioning ([#61](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/61)) 98 | 99 | ## 1.0.0 - 2022-02-12 100 | ### Feat 101 | - upgrade AWS provider to v4.0+ ([#57](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/57)) 102 | 103 | ### Fix 104 | - set the minimum terraform version to 1.1.4 ([#56](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/56)) 105 | 106 | ### BREAKING CHANGE 107 | resources regarding S3 bucket configurations need manual 108 | imports after upgrade. See `docs/upgrade-1.0.md` for guidance. 109 | 110 | ## 0.8.1 - 2022-01-10 111 | 112 | ## 0.8.0 - 2022-01-10 113 | ### Refactor 114 | - add tflint checks 115 | - simplify list item extractions ([#48](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/48)) 116 | - do not hard-code auth method in examples ([#46](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/46)) 117 | 118 | ## 0.7.0 - 2021-10-10 119 | ### Feat 120 | - support to create fixed bucket name ([#43](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/43)) 121 | - make s3 bucket replication optional ([#42](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/42)) 122 | - support logging for state Bucket ([#37](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/37)) 123 | 124 | ### Fix 125 | - make the fixed bucket name optional ([#44](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/44)) 126 | 127 | ## 0.6.0 - 2021-06-27 128 | ### Fix 129 | - conflicting operations on S3 buckets ([#33](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/33)) 130 | 131 | ### Refactor 132 | - add `required_providers` configuration ([#39](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/39)) 133 | 134 | ## 0.5.0 - 2021-06-06 135 | ### Feat 136 | - enable point-in-time recovery for DynamoDB table 137 | 138 | ## 0.4.1 - 2020-11-14 139 | ### Fix 140 | - interporation warnings 141 | 142 | ## 0.4.0 - 2020-09-21 143 | 144 | ## 0.3.1 - 2020-08-10 145 | ### Fix 146 | - make terraform_iam_policy to be a string ([#25](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/25)) 147 | 148 | ## 0.3.0 - 2020-08-10 149 | ### Fix 150 | - remove region attribute ([#24](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/issues/24)) 151 | 152 | ## 0.2.1 - 2019-08-18 153 | ### Fix 154 | - allow use of KMS keys by the replication role 155 | - encrypt state files in the replica bucket 156 | 157 | ## 0.2.0 - 2019-08-11 158 | ### Feat 159 | - add noncurrent_version_expiration option 160 | - add s3_bucket_force_destroy flag 161 | - move non-current versions to Glacier 162 | 163 | ### Fix 164 | - insufficient persmission to encrypt states with the KMS key 165 | 166 | ## 0.1.0 - 2019-08-10 167 | ### Feat 168 | - add "tags" input variable 169 | 170 | ## 0.0.4 - 2019-07-14 171 | ### Fix 172 | - use a provider for replica bucket 173 | 174 | ## 0.0.3 - 2019-07-14 175 | ### Feat 176 | - enable public access block for S3 buckets 177 | 178 | ## 0.0.2 - 2019-07-14 179 | ### Feat 180 | - derive a region for replica bucket from the provider 181 | -------------------------------------------------------------------------------- /replica.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | replication_role_count = var.iam_role_arn == null && var.enable_replication ? 1 : 0 3 | } 4 | 5 | data "aws_region" "replica" { 6 | count = var.enable_replication ? 1 : 0 7 | provider = aws.replica 8 | } 9 | 10 | #--------------------------------------------------------------------------------------------------- 11 | # KMS Key to Encrypt S3 Bucket 12 | #--------------------------------------------------------------------------------------------------- 13 | 14 | resource "aws_kms_key" "replica" { 15 | count = var.enable_replication ? 1 : 0 16 | provider = aws.replica 17 | 18 | description = var.kms_key_description 19 | deletion_window_in_days = var.kms_key_deletion_window_in_days 20 | enable_key_rotation = var.kms_key_enable_key_rotation 21 | 22 | tags = var.tags 23 | } 24 | 25 | #--------------------------------------------------------------------------------------------------- 26 | # Roles & Policies 27 | #--------------------------------------------------------------------------------------------------- 28 | 29 | # IAM Role for Replication 30 | # https://docs.aws.amazon.com/AmazonS3/latest/dev/crr-replication-config-for-kms-objects.html 31 | resource "aws_iam_role" "replication" { 32 | count = local.replication_role_count 33 | 34 | name_prefix = var.override_iam_role_name ? null : var.iam_role_name_prefix 35 | name = var.override_iam_role_name ? var.iam_role_name : null 36 | assume_role_policy = < 0 197 | error_message = "Input variable s3_bucket_name is invalid. Please refer to https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html." 198 | } 199 | } 200 | variable "s3_bucket_name_replica" { 201 | description = "If override_s3_bucket_name is true, use this bucket name for replica instead of dynamic name with bucket_prefix" 202 | type = string 203 | default = "" 204 | validation { 205 | condition = length(var.s3_bucket_name_replica) == 0 || length(regexall("^[a-z0-9][a-z0-9\\-.]{1,61}[a-z0-9]$", var.s3_bucket_name_replica)) > 0 206 | error_message = "Input variable s3_bucket_name_replica is invalid. Please refer to https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html." 207 | } 208 | } 209 | 210 | #--------------------------------------------------------------------------------------------------- 211 | # Optionally specifying a fixed iam policy name 212 | #--------------------------------------------------------------------------------------------------- 213 | 214 | variable "override_iam_policy_name" { 215 | description = "override iam policy name to disable policy_prefix and create policy with static name" 216 | type = bool 217 | default = false 218 | } 219 | 220 | variable "iam_policy_name" { 221 | description = "If override_iam_policy_name is true, use this policy name instead of dynamic name with policy_prefix" 222 | type = string 223 | default = "" 224 | } 225 | 226 | #--------------------------------------------------------------------------------------------------- 227 | # Optionally specifying a fixed iam role name 228 | #--------------------------------------------------------------------------------------------------- 229 | 230 | variable "override_iam_role_name" { 231 | description = "override iam role name to disable role_prefix and create role with static name" 232 | type = bool 233 | default = false 234 | } 235 | 236 | variable "iam_role_name" { 237 | description = "If override_iam_role_name is true, use this role name instead of dynamic name with role_prefix" 238 | type = string 239 | default = "" 240 | } 241 | 242 | #--------------------------------------------------------------------------------------------------- 243 | # Optionally specifying a fixed terraform iam policy name 244 | #--------------------------------------------------------------------------------------------------- 245 | 246 | variable "override_terraform_iam_policy_name" { 247 | description = "override terraform iam policy name to disable policy_prefix and create policy with static name" 248 | type = bool 249 | default = false 250 | } 251 | 252 | variable "terraform_iam_policy_name" { 253 | description = "If override_terraform_iam_policy_name is true, use this policy name instead of dynamic name with policy_prefix" 254 | type = string 255 | default = "" 256 | } 257 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-aws-remote-state-s3-backend 2 | 3 | [![Github Actions](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/actions/workflows/main.yml/badge.svg)](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/actions/workflows/main.yml) 4 | [![Releases](https://img.shields.io/github/v/release/nozaq/terraform-aws-remote-state-s3-backend)](https://github.com/nozaq/terraform-aws-remote-state-s3-backend/releases/latest) 5 | 6 | [Terraform Module Registry](https://registry.terraform.io/modules/nozaq/remote-state-s3-backend/aws) 7 | 8 | A terraform module to set up [remote state management](https://www.terraform.io/docs/state/remote.html) with [S3 backend](https://www.terraform.io/docs/backends/types/s3.html) for your account. It creates an encrypted S3 bucket to store state files and a DynamoDB table for state locking and consistency checking. 9 | Resources are defined following best practices as described in [the official document](https://www.terraform.io/docs/backends/types/s3.html#multi-account-aws-architecture) and [ozbillwang/terraform-best-practices](https://github.com/ozbillwang/terraform-best-practices). 10 | 11 | ## Features 12 | 13 | - Create a S3 bucket to store remote state files. 14 | - Encrypt state files with KMS. 15 | - Enable bucket replication and object versioning to prevent accidental data loss. 16 | - Automatically transit non-current versions in S3 buckets to AWS S3 Glacier to optimize the storage cost. 17 | - Optionally you can set to expire aged non-current versions(disabled by default). 18 | - Optionally you can set fixed S3 bucket name to be user friendly(false by default). 19 | - Create a DynamoDB table for state locking, encryption is optional. 20 | - Optionally create an IAM policy to allow permissions which Terraform needs. 21 | 22 | ## Usage 23 | 24 | The module outputs `terraform_iam_policy` which can be attached to IAM users, groups or roles running Terraform. This will allow the entity accessing remote state files and the locking table. This can optionally be disabled with `terraform_iam_policy_create = false` 25 | 26 | ```hcl 27 | provider "aws" { 28 | region = "us-east-1" 29 | } 30 | 31 | provider "aws" { 32 | alias = "replica" 33 | region = "us-west-1" 34 | } 35 | 36 | module "remote_state" { 37 | source = "nozaq/remote-state-s3-backend/aws" 38 | 39 | providers = { 40 | aws = aws 41 | aws.replica = aws.replica 42 | } 43 | } 44 | 45 | resource "aws_iam_user" "terraform" { 46 | name = "TerraformUser" 47 | } 48 | 49 | resource "aws_iam_user_policy_attachment" "remote_state_access" { 50 | user = aws_iam_user.terraform.name 51 | policy_arn = module.remote_state.terraform_iam_policy.arn 52 | } 53 | ``` 54 | 55 | Note that you need to provide two providers, one for the main state bucket and the other for the bucket to which the main state bucket is replicated to. Two providers must point to different AWS regions. 56 | 57 | Once resources are created, you can configure your terraform files to use the S3 backend as follows. 58 | 59 | ```hcl 60 | terraform { 61 | backend "s3" { 62 | bucket = "THE_NAME_OF_THE_STATE_BUCKET" 63 | key = "some_environment/terraform.tfstate" 64 | region = "us-east-1" 65 | encrypt = true 66 | kms_key_id = "THE_ID_OF_THE_KMS_KEY" 67 | dynamodb_table = "THE_ID_OF_THE_DYNAMODB_TABLE" 68 | } 69 | } 70 | ``` 71 | 72 | `THE_NAME_OF_THE_STATE_BUCKET`, `THE_ID_OF_THE_DYNAMODB_TABLE` and `THE_ID_OF_THE_KMS_KEY` can be replaced by `state_bucket.bucket`, `dynamodb_table.id` and `kms_key.id` in outputs from this module respectively. 73 | 74 | See [the official document](https://www.terraform.io/docs/backends/types/s3.html#example-configuration) for more detail. 75 | 76 | ## Compatibility 77 | 78 | - Starting from v1.0, this module requires [Terraform Provider for AWS](https://github.com/terraform-providers/terraform-provider-aws) v4.0 or later. [Version 1.0 Upgrade Guide](./docs/upgrade-1.0.md) described the recommended procedure after the upgrade. 79 | 80 | 81 | ## Requirements 82 | 83 | | Name | Version | 84 | |------|---------| 85 | | [terraform](#requirement\_terraform) | >= 1.1.4 | 86 | | [aws](#requirement\_aws) | >= 4.3 | 87 | 88 | ## Providers 89 | 90 | | Name | Version | 91 | |------|---------| 92 | | [aws](#provider\_aws) | >= 4.3 | 93 | | [aws.replica](#provider\_aws.replica) | >= 4.3 | 94 | 95 | ## Inputs 96 | 97 | | Name | Description | Type | Required | 98 | |------|-------------|------|:--------:| 99 | | [dynamodb\_deletion\_protection\_enabled](#input\_dynamodb\_deletion\_protection\_enabled) | Whether or not to enable deletion protection on the DynamoDB table | `bool` | no | 100 | | [dynamodb\_enable\_server\_side\_encryption](#input\_dynamodb\_enable\_server\_side\_encryption) | Whether or not to enable encryption at rest using an AWS managed KMS customer master key (CMK) | `bool` | no | 101 | | [dynamodb\_table\_billing\_mode](#input\_dynamodb\_table\_billing\_mode) | Controls how you are charged for read and write throughput and how you manage capacity. | `string` | no | 102 | | [dynamodb\_table\_name](#input\_dynamodb\_table\_name) | The name of the DynamoDB table to use for state locking. | `string` | no | 103 | | [enable\_replication](#input\_enable\_replication) | Set this to true to enable S3 bucket replication in another region | `bool` | no | 104 | | [iam\_policy\_attachment\_name](#input\_iam\_policy\_attachment\_name) | The name of the attachment. | `string` | no | 105 | | [iam\_policy\_name](#input\_iam\_policy\_name) | If override\_iam\_policy\_name is true, use this policy name instead of dynamic name with policy\_prefix | `string` | no | 106 | | [iam\_policy\_name\_prefix](#input\_iam\_policy\_name\_prefix) | Creates a unique name beginning with the specified prefix. | `string` | no | 107 | | [iam\_role\_arn](#input\_iam\_role\_arn) | Use IAM role of specified ARN for s3 replication instead of creating it. | `string` | no | 108 | | [iam\_role\_name](#input\_iam\_role\_name) | If override\_iam\_role\_name is true, use this role name instead of dynamic name with role\_prefix | `string` | no | 109 | | [iam\_role\_name\_prefix](#input\_iam\_role\_name\_prefix) | Creates a unique name beginning with the specified prefix. | `string` | no | 110 | | [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | Use permissions\_boundary with the replication IAM role. | `string` | no | 111 | | [kms\_key\_alias](#input\_kms\_key\_alias) | The alias for the KMS key as viewed in AWS console. It will be automatically prefixed with `alias/` | `string` | no | 112 | | [kms\_key\_deletion\_window\_in\_days](#input\_kms\_key\_deletion\_window\_in\_days) | Duration in days after which the key is deleted after destruction of the resource, must be between 7 and 30 days. | `number` | no | 113 | | [kms\_key\_description](#input\_kms\_key\_description) | The description of the key as viewed in AWS console. | `string` | no | 114 | | [kms\_key\_enable\_key\_rotation](#input\_kms\_key\_enable\_key\_rotation) | Specifies whether key rotation is enabled. | `bool` | no | 115 | | [noncurrent\_version\_expiration](#input\_noncurrent\_version\_expiration) | Specifies when noncurrent object versions expire. See the aws\_s3\_bucket document for detail. |
object({
days = number
})
| no | 116 | | [noncurrent\_version\_transitions](#input\_noncurrent\_version\_transitions) | Specifies when noncurrent object versions transitions. See the aws\_s3\_bucket document for detail. |
list(object({
days = number
storage_class = string
}))
| no | 117 | | [override\_iam\_policy\_name](#input\_override\_iam\_policy\_name) | override iam policy name to disable policy\_prefix and create policy with static name | `bool` | no | 118 | | [override\_iam\_role\_name](#input\_override\_iam\_role\_name) | override iam role name to disable role\_prefix and create role with static name | `bool` | no | 119 | | [override\_s3\_bucket\_name](#input\_override\_s3\_bucket\_name) | override s3 bucket name to disable bucket\_prefix and create bucket with static name | `bool` | no | 120 | | [override\_terraform\_iam\_policy\_name](#input\_override\_terraform\_iam\_policy\_name) | override terraform iam policy name to disable policy\_prefix and create policy with static name | `bool` | no | 121 | | [replica\_bucket\_prefix](#input\_replica\_bucket\_prefix) | Creates a unique replica bucket name beginning with the specified prefix. | `string` | no | 122 | | [s3\_bucket\_force\_destroy](#input\_s3\_bucket\_force\_destroy) | A boolean that indicates all objects should be deleted from S3 buckets so that the buckets can be destroyed without error. These objects are not recoverable. | `bool` | no | 123 | | [s3\_bucket\_name](#input\_s3\_bucket\_name) | If override\_s3\_bucket\_name is true, use this bucket name instead of dynamic name with bucket\_prefix | `string` | no | 124 | | [s3\_bucket\_name\_replica](#input\_s3\_bucket\_name\_replica) | If override\_s3\_bucket\_name is true, use this bucket name for replica instead of dynamic name with bucket\_prefix | `string` | no | 125 | | [s3\_logging\_target\_bucket](#input\_s3\_logging\_target\_bucket) | The name of the bucket for log storage. The "S3 log delivery group" should have Objects-write und ACL-read permissions on the bucket. | `string` | no | 126 | | [s3\_logging\_target\_prefix](#input\_s3\_logging\_target\_prefix) | The prefix to apply on bucket logs, e.g "logs/". | `string` | no | 127 | | [state\_bucket\_prefix](#input\_state\_bucket\_prefix) | Creates a unique state bucket name beginning with the specified prefix. | `string` | no | 128 | | [tags](#input\_tags) | A mapping of tags to assign to resources. | `map(string)` | no | 129 | | [terraform\_iam\_policy\_create](#input\_terraform\_iam\_policy\_create) | Specifies whether to terraform IAM policy is created. | `bool` | no | 130 | | [terraform\_iam\_policy\_name](#input\_terraform\_iam\_policy\_name) | If override\_terraform\_iam\_policy\_name is true, use this policy name instead of dynamic name with policy\_prefix | `string` | no | 131 | | [terraform\_iam\_policy\_name\_prefix](#input\_terraform\_iam\_policy\_name\_prefix) | Creates a unique name beginning with the specified prefix. | `string` | no | 132 | 133 | ## Outputs 134 | 135 | | Name | Description | 136 | |------|-------------| 137 | | [dynamodb\_table](#output\_dynamodb\_table) | The DynamoDB table to manage lock states. | 138 | | [kms\_key](#output\_kms\_key) | The KMS customer master key to encrypt state buckets. | 139 | | [kms\_key\_alias](#output\_kms\_key\_alias) | The alias of the KMS customer master key used to encrypt state bucket and dynamodb. | 140 | | [kms\_key\_replica](#output\_kms\_key\_replica) | The KMS customer master key to encrypt replica bucket and dynamodb. | 141 | | [replica\_bucket](#output\_replica\_bucket) | The S3 bucket to replicate the state S3 bucket. | 142 | | [state\_bucket](#output\_state\_bucket) | The S3 bucket to store the remote state file. | 143 | | [terraform\_iam\_policy](#output\_terraform\_iam\_policy) | The IAM Policy to access remote state environment. | 144 | 145 | --------------------------------------------------------------------------------