├── .github ├── conventional-commit-lint.yaml ├── release-please.yml ├── renovate.json ├── trusted-contribution.yml └── workflows │ ├── lint.yaml │ └── stale.yml ├── .gitignore ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── build ├── int.cloudbuild.yaml └── lint.cloudbuild.yaml ├── docs ├── upgrading_to_v2.0.md ├── upgrading_to_v4.0.md ├── upgrading_to_v8.0.md └── upgrading_to_v9.0.md ├── examples ├── multiple_buckets │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── simple_bucket │ ├── README.md │ ├── main.tf │ ├── variables.tf │ └── versions.tf ├── helpers └── combine_docfiles.py ├── main.tf ├── metadata.display.yaml ├── metadata.yaml ├── modules └── simple_bucket │ ├── README.md │ ├── main.tf │ ├── metadata.display.yaml │ ├── metadata.yaml │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── outputs.tf ├── test ├── integration │ ├── discover_test.go │ ├── go.mod │ ├── go.sum │ └── multiple_buckets │ │ └── multiple_buckets_test.go └── setup │ ├── .gitignore │ ├── iam.tf │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── variables.tf └── versions.tf /.github/conventional-commit-lint.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | enabled: true 19 | always_check_pr_title: true 20 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | releaseType: terraform-module 16 | handleGHRelease: true 17 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>GoogleCloudPlatform/cloud-foundation-toolkit//infra/terraform/test-org/github/resources/renovate"] 4 | } 5 | -------------------------------------------------------------------------------- /.github/trusted-contribution.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | annotations: 19 | - type: comment 20 | text: "/gcbrun" 21 | trustedContributors: 22 | - release-please[bot] 23 | - renovate[bot] 24 | - renovate-bot 25 | - forking-renovate[bot] 26 | - dependabot[bot] 27 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from values at: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf 17 | 18 | name: 'lint' 19 | 20 | on: 21 | workflow_dispatch: 22 | pull_request: 23 | branches: 24 | - main 25 | 26 | concurrency: 27 | group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}' 28 | cancel-in-progress: true 29 | 30 | jobs: 31 | lint: 32 | name: 'lint' 33 | runs-on: 'ubuntu-latest' 34 | steps: 35 | - uses: 'actions/checkout@v4' 36 | - id: variables 37 | run: | 38 | MAKEFILE=$(find . -name Makefile -print -quit) 39 | if [ -z "$MAKEFILE" ]; then 40 | echo dev-tools=gcr.io/cloud-foundation-cicd/cft/developer-tools:1 >> "$GITHUB_OUTPUT" 41 | else 42 | VERSION=$(grep "DOCKER_TAG_VERSION_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) 43 | IMAGE=$(grep "DOCKER_IMAGE_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) 44 | REGISTRY=$(grep "REGISTRY_URL := " $MAKEFILE | cut -d\ -f3) 45 | echo dev-tools=${REGISTRY}/${IMAGE}:${VERSION} >> "$GITHUB_OUTPUT" 46 | fi 47 | - run: docker run --rm -e ENABLE_BPMETADATA -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} module-swapper 48 | env: 49 | ENABLE_BPMETADATA: 1 50 | 51 | - run: docker run --rm -e ENABLE_BPMETADATA -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} /usr/local/bin/test_lint.sh 52 | env: 53 | ENABLE_BPMETADATA: 1 54 | 55 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | name: "Close stale issues" 19 | on: 20 | schedule: 21 | - cron: "0 23 * * *" 22 | 23 | jobs: 24 | stale: 25 | if: github.repository_owner == 'GoogleCloudPlatform' || github.repository_owner == 'terraform-google-modules' 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/stale@v9 29 | with: 30 | repo-token: ${{ secrets.GITHUB_TOKEN }} 31 | stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' 32 | stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' 33 | exempt-issue-labels: 'triaged' 34 | exempt-pr-labels: 'dependencies,autorelease: pending' 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX leaves these everywhere on SMB shares 2 | ._* 3 | 4 | # VS Code 5 | .vscode 6 | 7 | # OSX trash 8 | .DS_Store 9 | 10 | # Python 11 | *.pyc 12 | 13 | # Emacs save files 14 | *~ 15 | \#*\# 16 | .\#* 17 | 18 | # Vim-related files 19 | [._]*.s[a-w][a-z] 20 | [._]s[a-w][a-z] 21 | *.un~ 22 | Session.vim 23 | .netrwhist 24 | 25 | ### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore 26 | 27 | # Local .terraform directories 28 | **/.terraform/* 29 | 30 | # .tfstate files 31 | *.tfstate 32 | *.tfstate.* 33 | 34 | # Crash log files 35 | crash.log 36 | 37 | # Kitchen files 38 | **/inspec.lock 39 | **/.kitchen 40 | **/kitchen.local.yml 41 | **/Gemfile.lock 42 | 43 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 44 | # .tfvars files are managed as part of configuration and so should be included in 45 | # version control. 46 | test/source.sh 47 | **/*.tfvars 48 | 49 | credentials.json 50 | 51 | # avoid versioning of credentials generated in codelab 52 | # https://codelabs.developers.google.com/cft-onboarding?hl=en#3 53 | cft.json 54 | 55 | # tf lock file 56 | .terraform.lock.hcl 57 | -------------------------------------------------------------------------------- /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 6 | [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 7 | and this project adheres to 8 | [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 9 | 10 | ## [11.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v10.0.2...v11.0.0) (2025-05-30) 11 | 12 | 13 | ### ⚠ BREAKING CHANGES 14 | 15 | * **tf>=1.3:** bump TF to >=1.3 ([#367](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/367)) 16 | * add hierarchical namespace flag ([#375](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/375)) 17 | 18 | ### Features 19 | 20 | * add hierarchical namespace flag ([#375](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/375)) ([b65e3eb](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/b65e3ebf1c4df261355afb57e63fbd033cb8ea36)) 21 | 22 | 23 | ### Bug Fixes 24 | 25 | * **tf>=1.3:** bump TF to >=1.3 ([#367](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/367)) ([b5b0362](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/b5b036297c8761b05a60aaeb21dd822f4e360e36)) 26 | 27 | ## [10.0.2](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v10.0.1...v10.0.2) (2025-05-19) 28 | 29 | 30 | ### Bug Fixes 31 | 32 | * Making retention_policy is_locked as optional field ([#394](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/394)) ([e823780](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/e823780aac5d8c7268f7e930f59d76798485c6e0)) 33 | 34 | ## [10.0.1](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v10.0.0...v10.0.1) (2025-03-18) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * Update apphub service_uri to be available after apply ([#390](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/390)) ([66e472b](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/66e472b56cd21b45a3939883a66ccfcf5ec1b9ed)) 40 | 41 | ## [10.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v9.1.0...v10.0.0) (2025-03-14) 42 | 43 | 44 | ### ⚠ BREAKING CHANGES 45 | 46 | * **deps:** Update Terraform terraform-google-modules/kms/google to v4 ([#384](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/384)) 47 | * add concrete variable types ([#387](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/387)) 48 | * added concrete types for simple sa variables ([#386](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/386)) 49 | 50 | ### Bug Fixes 51 | 52 | * add concrete variable types ([#387](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/387)) ([1fa5c70](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/1fa5c7017201fa645c630a53a58bed4925e42c6b)) 53 | * added concrete types for simple sa variables ([#386](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/386)) ([534a547](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/534a547ead0308d39c12d023f19dc541ae1470c7)) 54 | * **deps:** Update Terraform terraform-google-modules/kms/google to v4 ([#384](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/384)) ([d9ca2c4](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/d9ca2c4433cda865b090bbbd5f3a1ae3f5514c41)) 55 | 56 | ## [9.1.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v9.0.2...v9.1.0) (2025-02-13) 57 | 58 | 59 | ### Features 60 | 61 | * add output required for apphub registration for simple_bucket module ([#383](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/383)) ([fbc43db](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/fbc43db125c5096f741acfc300f4d9a774d6e3bf)) 62 | 63 | ## [9.0.2](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v9.0.1...v9.0.2) (2025-01-29) 64 | 65 | 66 | ### Bug Fixes 67 | 68 | * update description for encryption input variable of simple-bucket ([#380](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/380)) ([31dd911](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/31dd911ccb7b590af834166195c61690653037ac)) 69 | 70 | ## [9.0.1](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v9.0.0...v9.0.1) (2025-01-16) 71 | 72 | 73 | ### Bug Fixes 74 | 75 | * update display metadata ([#377](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/377)) ([684b909](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/684b90921cc2261c8181557cd7c3c324c94ba04c)) 76 | 77 | ## [9.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v8.0.3...v9.0.0) (2024-12-13) 78 | 79 | 80 | ### ⚠ BREAKING CHANGES 81 | 82 | * remove apphub_service_uri from output of simple_bucket ([#372](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/372)) 83 | 84 | ### Bug Fixes 85 | 86 | * remove apphub_service_uri from output of simple_bucket ([#372](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/372)) ([7459e41](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/7459e41091602c41c486681e148b8ca7c4dc15c0)) 87 | 88 | ## [8.0.3](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v8.0.2...v8.0.3) (2024-12-01) 89 | 90 | 91 | ### Bug Fixes 92 | 93 | * add output type for internal_kms_configuration ([#370](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/370)) ([ddc3ab0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/ddc3ab0822d4c42de8041ba29d200d55964e0c26)) 94 | 95 | ## [8.0.2](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v8.0.1...v8.0.2) (2024-11-27) 96 | 97 | 98 | ### Bug Fixes 99 | 100 | * Update variable's order in variables.tf and update display metad… ([#368](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/368)) ([29eb7e2](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/29eb7e2cd361076f17c9c565be74cb8ebd2fd6df)) 101 | 102 | ## [8.0.1](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v8.0.0...v8.0.1) (2024-10-28) 103 | 104 | 105 | ### Bug Fixes 106 | 107 | * Fix apphub uri and id representation ([#360](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/360)) ([2782340](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/2782340b070823f8cc684bb81184f3cb9d4c97c3)) 108 | 109 | ## [8.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v7.0.0...v8.0.0) (2024-10-17) 110 | 111 | 112 | ### ⚠ BREAKING CHANGES 113 | 114 | * fix count invalid argument on simple bucket ([#355](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/355)) 115 | 116 | ### Features 117 | 118 | * Add Apphub URI output to cloud storage ([#358](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/358)) ([209d5e3](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/209d5e3ec29580fd6c0f3eecab5f5b020159605a)) 119 | 120 | 121 | ### Bug Fixes 122 | 123 | * fix count invalid argument on simple bucket ([#355](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/355)) ([8fe9a7e](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/8fe9a7e1ce9dc8d068b4bc1f36c53281e18090b8)) 124 | 125 | ## [7.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v6.1.0...v7.0.0) (2024-10-14) 126 | 127 | 128 | ### ⚠ BREAKING CHANGES 129 | 130 | * **deps:** Update Terraform terraform-google-modules/kms/google to v3 ([#343](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/343)) 131 | * **TPG>=5.43:** replacing "no_age" -> "send_age_if_zero" ([#340](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/340)) 132 | 133 | ### Bug Fixes 134 | 135 | * **deps:** Update Terraform terraform-google-modules/kms/google to v3 ([#343](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/343)) ([e8bb6eb](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/e8bb6eb49fdaf5f6f300d1b6dc46f097173dc488)) 136 | * **TPG>=5.43:** replacing "no_age" -> "send_age_if_zero" ([#340](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/340)) ([f40bf31](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f40bf318a55aa12d467cebac8706f774481958ac)) 137 | * use null as default for lookup ([#332](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/332)) ([6c14d5e](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/6c14d5e50e2f29f21af870785eb89a862724d067)) 138 | 139 | ## [6.1.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v6.0.1...v6.1.0) (2024-08-29) 140 | 141 | 142 | ### Features 143 | 144 | * **deps:** Update Terraform google to v6 ([#336](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/336)) ([2fa380d](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/2fa380d0a15f7daf776bb80019a11594aed5a5bf)) 145 | * Encrypt bucket with CMEK ([#325](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/325)) ([07e3a4e](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/07e3a4e2b34dc4c7a2a99ae5e6893a3670251870)) 146 | 147 | ## [6.0.1](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v6.0.0...v6.0.1) (2024-07-03) 148 | 149 | 150 | ### Bug Fixes 151 | 152 | * adding "no_age" param in simple bucket ([#319](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/319)) ([87e66bb](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/87e66bb7af2f88e29db6a9fe1eda9bf53fe119bb)) 153 | * lookup default value for soft delete policy ([#318](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/318)) ([aa7c57e](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/aa7c57e92e691a22433092bceea9de879f66d7ab)) 154 | 155 | ## [6.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v5.0.0...v6.0.0) (2024-05-03) 156 | 157 | 158 | ### ⚠ BREAKING CHANGES 159 | 160 | * soft-delete configuration ([#309](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/309)) 161 | 162 | ### Features 163 | 164 | * soft-delete configuration ([#309](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/309)) ([1be844a](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/1be844a778afe5a060ba1a686ab1187396e8e267)) 165 | 166 | ## [5.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v4.0.1...v5.0.0) (2023-10-17) 167 | 168 | 169 | ### ⚠ BREAKING CHANGES 170 | 171 | * **TPG >= 4.46:** adds support to autoclass ([#265](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/265)) 172 | 173 | ### Features 174 | 175 | * **TPG >= 4.46:** adds support to autoclass ([#265](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/265)) ([52eaa5a](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/52eaa5ae08e419340933b9b8c78e0d249d9e72bd)) 176 | 177 | 178 | ### Bug Fixes 179 | 180 | * upgraded versions.tf to include minor bumps from tpg v5 ([#276](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/276)) ([b94c2f9](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/b94c2f9fa00f21e6a329ce221a1282ce4455c1b8)) 181 | 182 | ## [4.0.1](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v4.0.0...v4.0.1) (2023-08-03) 183 | 184 | 185 | ### Bug Fixes 186 | 187 | * create random suffix resource on demand ([#185](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/185)) ([5050c91](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/5050c91efee42e94bac886f0d86ee7a76cc42058)) 188 | * lifecycle_rule optional condition is_live failing when missing ([#246](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/246)) ([c8111a4](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/c8111a4fc877d1af2785820c31c8c02a22a43206)) 189 | 190 | ## [4.0.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v3.4.1...v4.0.0) (2023-04-06) 191 | 192 | 193 | ### ⚠ BREAKING CHANGES 194 | 195 | * add support for custom_placement_config ([#231](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/231)) 196 | * **TPG >= 4.42:** add support for public_access_prevention ([#218](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/218)) 197 | * location inverse control in bucket name prefix ([#186](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/186)) 198 | * Add matches_prefix and matches_suffix conditions ([#202](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/202)) 199 | 200 | ### Features 201 | 202 | * Add matches_prefix and matches_suffix conditions ([#202](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/202)) ([8db2eb3](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/8db2eb352c3998b4981553e2bdeb72c2c7c34f5b)) 203 | * add support for custom_placement_config ([#231](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/231)) ([a0bbdbd](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/a0bbdbdbafa4732c8b3aa1a7760216fd48df43f3)) 204 | * Hmac access ([#181](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/181)) ([e5e4909](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/e5e49094165ce876479f6a852889b17726807caa)) 205 | * location inverse control in bucket name prefix ([#186](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/186)) ([dbd3c35](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/dbd3c3528332fc84bc599348279eaf501826a0f0)) 206 | * **TPG >= 4.42:** add support for public_access_prevention ([#218](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/218)) ([4469954](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/4469954690e29f8145d185ecb7ec345cd9f9abab)) 207 | 208 | ## [3.4.1](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v3.4.0...v3.4.1) (2023-01-04) 209 | 210 | 211 | ### Bug Fixes 212 | 213 | * fixes lint issues and generates metadata ([#207](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/207)) ([f038511](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f038511fc58371f51255cc8921d31b0da82094f5)) 214 | * relax random provider version ([#212](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/212)) ([2d7da45](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/2d7da4521ea639977d177f6fd5f4f51444a09543)) 215 | 216 | ## [3.4.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v3.3.0...v3.4.0) (2022-09-12) 217 | 218 | 219 | ### Features 220 | 221 | * Add var to define different lifecycle rules for each bucket ([#169](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/169)) ([4793dd2](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/4793dd22f0fa75ff5f27221971ee2af7317d805e)) 222 | 223 | ## [3.3.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v3.2.0...v3.3.0) (2022-07-15) 224 | 225 | 226 | ### Features 227 | 228 | * add name and url outputs on simple_bucket module ([#175](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/175)) ([d76ffa3](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/d76ffa3f2f147042527d98333397355a387d6701)) 229 | * Add option to enable default_event_based_hold argument ([#178](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/178)) ([2ab4888](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/2ab4888d135014b4c74c296da7e2e381aa58f766)) 230 | 231 | ## [3.2.0](https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v3.1.0...v3.2.0) (2022-03-04) 232 | 233 | 234 | ### Features 235 | 236 | * add support for website configuration to simple_bucket submodule ([#150](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/150)) ([839a18c](https://github.com/terraform-google-modules/terraform-google-cloud-storage/commit/839a18c4de5d7c00c74a54dfde51280862f4e8b5)) 237 | 238 | ## [3.1.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v3.0.0...v3.1.0) (2021-11-18) 239 | 240 | 241 | ### Features 242 | 243 | * Add missing lifecycle rules conditions simple_bucket ([#145](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/145)) ([bbb681d](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/bbb681d2335462c8e5a1234910d509782a06732b)), closes [#144](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/144) 244 | * update TPG version constraints to allow 4.0 ([#143](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/143)) ([2e4c375](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/2e4c375bd2ea05ef9a4ff8fc44055ccf4bb1420a)) 245 | 246 | ## [3.0.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v2.2.0...v3.0.0) (2021-09-27) 247 | 248 | 249 | ### ⚠ BREAKING CHANGES 250 | 251 | * The default storage class has been changed from `MULTI_REGIONAL` to `STANDARD`. This new default is [recommended](https://cloud.google.com/storage/docs/storage-classes#standard) and can be used for multi-regional storage. 252 | 253 | ### Features 254 | 255 | * add additional lifecycle conditions: custom_time_before, days_since_noncurrent_time, noncurrent_time_before ([#135](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/135)) ([bd1d1e7](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/bd1d1e7bae83e9cc1d64019f06d2ca1b9d50a67f)) 256 | 257 | 258 | ### Bug Fixes 259 | 260 | * Change default storage class to `STANDARD` ([#137](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/137)) ([af10280](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/af10280a5055dcf8823a4fe09052e94a97eb0688)) 261 | 262 | ## [2.2.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v2.1.0...v2.2.0) (2021-09-17) 263 | 264 | 265 | ### Features 266 | 267 | * Add ability to append a randomized suffix to all bucket names ([#130](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/130)) ([93ff75f](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/93ff75fb291c998c7d495c55342aea3b461fcc1a)) 268 | * Add support for retention policy ([#127](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/127)) ([a0982c9](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/a0982c94f92df37d903af0a85e7ee5fe1e655d1e)) 269 | * Support for CORS in simple bucket ([#128](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/128)) ([e6559e9](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/e6559e9f4721d5b67eec1644ebbefac852cf55e8)) 270 | 271 | 272 | ### Bug Fixes 273 | 274 | * Correct behavior of website and cors variables. ([#132](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/132)) ([3e6e7f4](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/3e6e7f405dc4d3698f1dabfd23440d67908f2e2f)) 275 | 276 | ## [2.1.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v2.0.0...v2.1.0) (2021-06-15) 277 | 278 | 279 | ### Features 280 | 281 | * add support for days_since_custom_time ([#120](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/120)) ([0247454](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/02474541f50146ae8dff3aa146ff6f8f278e041c)) 282 | * Add support for log bucket configuration ([#117](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/117)) ([eca9c57](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/eca9c57551e48e4fff635df8c59d2797b78c6652)) 283 | 284 | ## [2.0.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.7.1...v2.0.0) (2021-05-17) 285 | 286 | 287 | ### ⚠ BREAKING CHANGES 288 | 289 | * Added Terraform 0.13 constraint and module attribution (#105) 290 | * The resource state locations have changed to use for_each, please see the [upgrade guide](https://github.com/terraform-google-modules/terraform-google-cloud-storage/blob/master/docs/upgrading_to_v2.0.md) for details. 291 | 292 | ### Features 293 | 294 | * add Terraform 0.13 constraint and module attribution ([#105](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/105)) ([b33d674](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/b33d67417d2e4309e9774811e0e14c612c300f6c)) 295 | * Allow setting storage.admin and storage.hmacKeyAdmin roles ([#95](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/95)) ([9f6085e](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/9f6085e671eea558585f4c5027bd94f1bcdd4a11)) 296 | * Use for_each instead of count to create resource ([#86](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/86)) ([af73533](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/af735332c091c6fe5de082562c8d59f979421611)) 297 | 298 | 299 | ### Bug Fixes 300 | 301 | * Fix deprecation of is_live lifecycle rule ([#91](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/91)) ([f73041b](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f73041b904d8f5c7020efb84737d54869e394738)) 302 | * Remove deprecated list() function usage ([#107](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/107)) ([1fe315a](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/1fe315a8ab722d7f91b60e1c209bf938724eb371)) 303 | * Use correct IAM view role in example ([#115](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/115)) ([4a9931d](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/4a9931dc339216fc5edb815c681168fd7063424c)) 304 | 305 | ### [1.7.2](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.7.1...v1.7.2) (2020-09-30) 306 | 307 | ### Bug Fixes 308 | 309 | * Fix deprecation of is_live lifecycle rule ([#91](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/91)) ([f73041b](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f73041b904d8f5c7020efb84737d54869e394738)) 310 | 311 | ### [1.7.1](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.7.0...v1.7.1) (2020-09-21) 312 | 313 | 314 | ### Bug Fixes 315 | 316 | * Constrain minimum Google provider version to 3.38 ([#84](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/84)) ([ebc1916](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/ebc19161e2b9c24ef41c2c5898b2d65eae81ee1e)) 317 | 318 | ## [1.7.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.6.0...v1.7.0) (2020-09-16) 319 | 320 | ### ⚠ BREAKING CHANGES 321 | 322 | * Minimum Google provider version increased to [3.38.0](https://github.com/hashicorp/terraform-provider-google/blob/master/CHANGELOG.md#3380-september-08-2020) 323 | 324 | 325 | ### Features 326 | 327 | * Add is_live field to simple_bucket lifecycle ([#76](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/76)) ([a16305d](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/a16305dfad12ef06881a73a6c2a33fe7fe569bfb)) 328 | 329 | 330 | ### Bug Fixes 331 | 332 | * Use uniform_bucket_level_access flag instead due to deprecation ([#80](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/80)) ([f287581](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f287581701bdcb0af996a26a8b922788cf686f57)) 333 | 334 | 335 | 336 | ## [1.6.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.5.0...v1.6.0) (2020-05-26) 337 | 338 | 339 | ### Features 340 | 341 | * Add support for cors and website config in variables ([#63](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/63)) ([69dafb3](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/69dafb3b3c532013919f4da416fa72aa009621a3)) 342 | * Add support for creating folders in buckets with folders variable ([#59](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/59)) ([0fa0689](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/0fa068980e4d01b66f5f0f2d923f6fae730b1151)) 343 | 344 | 345 | ### Bug Fixes 346 | 347 | * convert lifecycle action object to map ([#52](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/52)) ([f2e6ea3](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f2e6ea3e1954c8311ff326d7c512756db1dd5ae9)) 348 | 349 | ## [1.5.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.4.0...v1.5.0) (2020-04-22) 350 | 351 | 352 | ### Features 353 | 354 | * add support for lifecycle rules in simple bucket ([#49](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/49)) ([b39e2cd](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/b39e2cdf0848b59d00dd7fe65c917a5bf4a1176a)) 355 | 356 | ## [1.4.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.3.0...v1.4.0) (2020-03-04) 357 | 358 | 359 | ### Features 360 | 361 | * add outputs for simple bucket module ([#38](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/38)) ([f93bf5d](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/f93bf5d88842018f8421be61af5a0f4afd947487)) 362 | 363 | 364 | ### Bug Fixes 365 | 366 | * Adding type constraints to variables ([#43](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/43)) ([45d42a1](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/45d42a1d7f73f8c4ad77d1455de77ce88ab0e8ad)) 367 | 368 | ## [1.3.0](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.2.0...v1.3.0) (2020-02-13) 369 | 370 | 371 | ### Features 372 | 373 | * Add simple bucket submodule ([#35](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/35)) ([e75114a](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/e75114a5770d8aab65764d4c04a36c52bde4f073)) 374 | * Add support for customer encryption keys ([#34](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/34)) ([32eff9b](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/32eff9b9330e6c9bb683cfd75d0baf9d9798b7eb)) 375 | * replace dot on a dash in label value ([#31](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/issues/31)) ([8875ebb](https://www.github.com/terraform-google-modules/terraform-google-cloud-storage/commit/8875ebbc645e1a6196c61a9f4d0cfaf3fa0f6569)) 376 | 377 | ## [Unreleased] 378 | 379 | ## [1.2.0] - 2019-12-06 380 | 381 | ### Added 382 | 383 | - Added support for setting lifecycle rules [#19](https://github.com/terraform-google-modules/terraform-google-cloud-storage/pull/19) 384 | 385 | ## [1.1.0] - 2019-11-20 386 | 387 | ### Added 388 | 389 | - Include name of bucket as label for cost analysis [#20] 390 | 391 | ### Fixed 392 | 393 | - Error from the `names` and `urls` outputs caused by removing elements from the `names` variable. [#23] 394 | 395 | ## [1.0.0] - 2019-08-14 396 | 397 | ### Changed 398 | 399 | - Upgraded for usage with terraform-0.12.x [#9] 400 | - Added support for `force_destroy` attribute [#9] 401 | 402 | ## [0.1.0] - 2019-05-22 403 | 404 | ### Added 405 | 406 | - Initial release 407 | 408 | [Unreleased]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.2.0...HEAD 409 | [1.2.0]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.1.0...v1.2.0 410 | [1.1.0]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v1.0.0...v1.1.0 411 | [1.0.0]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/compare/v0.1.0...v1.0.0 412 | [0.1.0]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/releases/tag/v0.1.0 413 | 414 | [#23]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/pull/23 415 | [#20]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/pull/20 416 | [#9]: https://github.com/terraform-google-modules/terraform-google-cloud-storage/pull/9 417 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # NOTE: This file is automatically generated from values at: 2 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf 3 | 4 | * @terraform-google-modules/cft-admins @ayushmjain @q2w 5 | 6 | # NOTE: GitHub CODEOWNERS locations: 7 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-and-branch-protection 8 | 9 | CODEOWNERS @terraform-google-modules/cft-admins 10 | .github/CODEOWNERS @terraform-google-modules/cft-admins 11 | docs/CODEOWNERS @terraform-google-modules/cft-admins 12 | 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This document provides guidelines for contributing to the module. 4 | 5 | ## Dependencies 6 | 7 | The following dependencies must be installed on the development system: 8 | 9 | - [Docker Engine][docker-engine] 10 | - [Google Cloud SDK][google-cloud-sdk] 11 | - [make] 12 | 13 | ## Generating Documentation for Inputs and Outputs 14 | 15 | The Inputs and Outputs tables in the READMEs of the root module, 16 | submodules, and example modules are automatically generated based on 17 | the `variables` and `outputs` of the respective modules. These tables 18 | must be refreshed if the module interfaces are changed. 19 | 20 | ### Execution 21 | 22 | Run `make generate_docs` to generate new Inputs and Outputs tables. 23 | 24 | ## Integration Testing 25 | 26 | Integration tests are used to verify the behaviour of the root module, 27 | submodules, and example modules. Additions, changes, and fixes should 28 | be accompanied with tests. 29 | 30 | The integration tests are run using [Kitchen][kitchen], 31 | [Kitchen-Terraform][kitchen-terraform], and [InSpec][inspec]. These 32 | tools are packaged within a Docker image for convenience. 33 | 34 | The general strategy for these tests is to verify the behaviour of the 35 | [example modules](./examples/), thus ensuring that the root module, 36 | submodules, and example modules are all functionally correct. 37 | 38 | ### Test Environment 39 | The easiest way to test the module is in an isolated test project. The setup for such a project is defined in [test/setup](./test/setup/) directory. 40 | 41 | To use this setup, you need a service account with Project Creator access on a folder. Export the Service Account credentials to your environment like so: 42 | 43 | ``` 44 | export SERVICE_ACCOUNT_JSON=$(< credentials.json) 45 | ``` 46 | 47 | You will also need to set a few environment variables: 48 | ``` 49 | export TF_VAR_org_id="your_org_id" 50 | export TF_VAR_folder_id="your_folder_id" 51 | export TF_VAR_billing_account="your_billing_account_id" 52 | ``` 53 | 54 | With these settings in place, you can prepare a test project using Docker: 55 | ``` 56 | make docker_test_prepare 57 | ``` 58 | 59 | ### Noninteractive Execution 60 | 61 | Run `make docker_test_integration` to test all of the example modules 62 | noninteractively, using the prepared test project. 63 | 64 | ### Interactive Execution 65 | 66 | 1. Run `make docker_run` to start the testing Docker container in 67 | interactive mode. 68 | 69 | 1. Run `kitchen_do create ` to initialize the working 70 | directory for an example module. 71 | 72 | 1. Run `kitchen_do converge ` to apply the example module. 73 | 74 | 1. Run `kitchen_do verify ` to test the example module. 75 | 76 | 1. Run `kitchen_do destroy ` to destroy the example module 77 | state. 78 | 79 | ## Linting and Formatting 80 | 81 | Many of the files in the repository can be linted or formatted to 82 | maintain a standard of quality. 83 | 84 | ### Execution 85 | 86 | Run `make docker_test_lint`. 87 | 88 | [docker-engine]: https://www.docker.com/products/docker-engine 89 | [flake8]: http://flake8.pycqa.org/en/latest/ 90 | [gofmt]: https://golang.org/cmd/gofmt/ 91 | [google-cloud-sdk]: https://cloud.google.com/sdk/install 92 | [hadolint]: https://github.com/hadolint/hadolint 93 | [inspec]: https://inspec.io/ 94 | [kitchen-terraform]: https://github.com/newcontext-oss/kitchen-terraform 95 | [kitchen]: https://kitchen.ci/ 96 | [make]: https://en.wikipedia.org/wiki/Make_(software) 97 | [shellcheck]: https://www.shellcheck.net/ 98 | [terraform-docs]: https://github.com/segmentio/terraform-docs 99 | [terraform]: https://terraform.io/ 100 | 101 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Make will use bash instead of sh 16 | SHELL := /usr/bin/env bash 17 | 18 | DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.24 19 | DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools 20 | REGISTRY_URL := gcr.io/cloud-foundation-cicd 21 | 22 | # Enter docker container for local development 23 | .PHONY: docker_run 24 | docker_run: 25 | docker run --rm -it \ 26 | -e SERVICE_ACCOUNT_JSON \ 27 | -v $(CURDIR):/workspace \ 28 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 29 | /bin/bash 30 | 31 | # Execute prepare tests within the docker container 32 | .PHONY: docker_test_prepare 33 | docker_test_prepare: 34 | docker run --rm -it \ 35 | -e SERVICE_ACCOUNT_JSON \ 36 | -e TF_VAR_org_id \ 37 | -e TF_VAR_folder_id \ 38 | -e TF_VAR_billing_account \ 39 | -v $(CURDIR):/workspace \ 40 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 41 | /usr/local/bin/execute_with_credentials.sh prepare_environment 42 | 43 | # Clean up test environment within the docker container 44 | .PHONY: docker_test_cleanup 45 | docker_test_cleanup: 46 | docker run --rm -it \ 47 | -e SERVICE_ACCOUNT_JSON \ 48 | -e TF_VAR_org_id \ 49 | -e TF_VAR_folder_id \ 50 | -e TF_VAR_billing_account \ 51 | -v $(CURDIR):/workspace \ 52 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 53 | /usr/local/bin/execute_with_credentials.sh cleanup_environment 54 | 55 | # Execute integration tests within the docker container 56 | .PHONY: docker_test_integration 57 | docker_test_integration: 58 | docker run --rm -it \ 59 | -e SERVICE_ACCOUNT_JSON \ 60 | -v $(CURDIR):/workspace \ 61 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 62 | cft test run all 63 | 64 | # Execute lint tests within the docker container 65 | .PHONY: docker_test_lint 66 | docker_test_lint: 67 | docker run --rm -it \ 68 | -e ENABLE_BPMETADATA \ 69 | -v $(CURDIR):/workspace \ 70 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 71 | /usr/local/bin/test_lint.sh 72 | 73 | # Execute lint tests in github actions 74 | .PHONY: docker_test_lint_gha 75 | docker_test_lint_gha: 76 | docker run --rm \ 77 | -v $(CURDIR):/workspace \ 78 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 79 | /usr/local/bin/test_lint.sh --markdown --contrib-guide=../blob/master/CONTRIBUTING.md 80 | 81 | 82 | # Generate documentation 83 | .PHONY: docker_generate_docs 84 | docker_generate_docs: 85 | docker run --rm -it \ 86 | -e ENABLE_BPMETADATA \ 87 | -v $(CURDIR):/workspace \ 88 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 89 | /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_docs' 90 | 91 | # Alias for backwards compatibility 92 | .PHONY: generate_docs 93 | generate_docs: docker_generate_docs 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Google Cloud Storage Module 2 | 3 | This module makes it easy to create one or more GCS buckets, and assign basic permissions on them to arbitrary users. 4 | 5 | The resources/services/activations/deletions that this module will create/trigger are: 6 | 7 | - One or more GCS buckets 8 | - Zero or more IAM bindings for those buckets 9 | 10 | If you only wish to create a single bucket, consider using the 11 | [simple bucket](modules/simple_bucket) submodule instead. 12 | 13 | ## Compatibility 14 | This module is meant for use with Terraform 0.13+ and tested using Terraform 1.0+. If you find incompatibilities using Terraform >=0.13, please open an issue. 15 | If you haven't 16 | [upgraded](https://www.terraform.io/upgrade-guides/0-13.html) and need a Terraform 17 | 0.12.x-compatible version of this module, the last released version 18 | intended for Terraform 0.12.x is [v1.7.1](https://registry.terraform.io/modules/terraform-google-modules/-cloud-storage/google/v1.7.1). 19 | 20 | ## Usage 21 | 22 | Basic usage of this module is as follows: 23 | 24 | ```hcl 25 | module "gcs_buckets" { 26 | source = "terraform-google-modules/cloud-storage/google" 27 | version = "~> 11.0" 28 | project_id = "" 29 | names = ["first", "second"] 30 | prefix = "my-unique-prefix" 31 | set_admin_roles = true 32 | admins = ["group:foo-admins@example.com"] 33 | versioning = { 34 | first = true 35 | } 36 | bucket_admins = { 37 | second = "user:spam@example.com,user:eggs@example.com" 38 | } 39 | } 40 | ``` 41 | 42 | Functional examples are included in the 43 | [examples](./examples/) directory. 44 | 45 | 46 | ## Inputs 47 | 48 | | Name | Description | Type | Default | Required | 49 | |------|-------------|------|---------|:--------:| 50 | | admins | IAM-style members who will be granted roles/storage.objectAdmin on all buckets. | `list(string)` | `[]` | no | 51 | | autoclass | Optional map of lowercase unprefixed bucket name => boolean, defaults to false. | `map(bool)` | `{}` | no | 52 | | bucket\_admins | Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket admins. | `map(string)` | `{}` | no | 53 | | bucket\_creators | Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket creators. | `map(string)` | `{}` | no | 54 | | bucket\_hmac\_key\_admins | Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket HMAC Key admins. | `map(string)` | `{}` | no | 55 | | bucket\_lifecycle\_rules | Additional lifecycle\_rules for specific buckets. Map of lowercase unprefixed name => list of lifecycle rules to configure. |
map(set(object({
# Object with keys:
# - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass.
# - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule.
action = object({
type = string
storage_class = optional(string)
})

# Object with keys:
# - age - (Optional) Minimum age of an object in days to satisfy this condition.
# - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field.
# - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.
# - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY".
# - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY.
# - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition.
# - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition
# - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.
# - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition.
# - days_since_custom_time - (Optional) Days since the date set in the customTime metadata for the object.
# - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object.
# - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent.
condition = object({
age = optional(number)
send_age_if_zero = optional(bool)
created_before = optional(string)
with_state = optional(string)
matches_storage_class = optional(string)
matches_prefix = optional(string)
matches_suffix = optional(string)
num_newer_versions = optional(number)
custom_time_before = optional(string)
days_since_custom_time = optional(number)
days_since_noncurrent_time = optional(number)
noncurrent_time_before = optional(string)
})
})))
| `{}` | no | 56 | | bucket\_policy\_only | Disable ad-hoc ACLs on specified buckets. Defaults to true. Map of lowercase unprefixed name => boolean | `map(bool)` | `{}` | no | 57 | | bucket\_storage\_admins | Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket storage admins. | `map(string)` | `{}` | no | 58 | | bucket\_viewers | Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket viewers. | `map(string)` | `{}` | no | 59 | | cors | Set of maps of mixed type attributes for CORS values. See appropriate attribute types here: https://www.terraform.io/docs/providers/google/r/storage_bucket.html#cors |
list(object({
origin = optional(list(string))
method = optional(list(string))
response_header = optional(list(string))
max_age_seconds = optional(number)
}))
| `[]` | no | 60 | | creators | IAM-style members who will be granted roles/storage.objectCreators on all buckets. | `list(string)` | `[]` | no | 61 | | custom\_placement\_config | Map of lowercase unprefixed name => custom placement config object. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket#custom_placement_config | `any` | `{}` | no | 62 | | default\_event\_based\_hold | Enable event based hold to new objects added to specific bucket. Defaults to false. Map of lowercase unprefixed name => boolean | `map(bool)` | `{}` | no | 63 | | encryption\_key\_names | Optional map of lowercase unprefixed name => string, empty strings are ignored. | `map(string)` | `{}` | no | 64 | | folders | Map of lowercase unprefixed name => list of top level folder objects. | `map(list(string))` | `{}` | no | 65 | | force\_destroy | Optional map of lowercase unprefixed name => boolean, defaults to false. | `map(bool)` | `{}` | no | 66 | | hierarchical\_namespace | Optional map of lowercase unprefixed bucket name => boolean, defaults to false. | `map(bool)` | `{}` | no | 67 | | hmac\_key\_admins | IAM-style members who will be granted roles/storage.hmacKeyAdmin on all buckets. | `list(string)` | `[]` | no | 68 | | hmac\_service\_accounts | List of HMAC service accounts to grant access to GCS. | `map(string)` | `{}` | no | 69 | | labels | Labels to be attached to the buckets | `map(string)` | `{}` | no | 70 | | lifecycle\_rules | List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches\_storage\_class should be a comma delimited string. |
set(object({
# Object with keys:
# - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass.
# - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule.
action = object({
type = string
storage_class = optional(string)
})

# Object with keys:
# - age - (Optional) Minimum age of an object in days to satisfy this condition.
# - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field.
# - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.
# - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY".
# - matches_storage_class - (Optional) Comma delimited string for storage class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY.
# - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition.
# - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition.
# - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.
# - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition.
# - days_since_custom_time - (Optional) The number of days from the Custom-Time metadata attribute after which this condition becomes true.
# - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object.
# - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent.
condition = object({
age = optional(number)
send_age_if_zero = optional(bool)
created_before = optional(string)
with_state = optional(string)
matches_storage_class = optional(string)
matches_prefix = optional(string)
matches_suffix = optional(string)
num_newer_versions = optional(number)
custom_time_before = optional(string)
days_since_custom_time = optional(number)
days_since_noncurrent_time = optional(number)
noncurrent_time_before = optional(string)
})
}))
| `[]` | no | 71 | | location | Bucket location. | `string` | `"EU"` | no | 72 | | logging | Map of lowercase unprefixed name => bucket logging config object. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#logging | `any` | `{}` | no | 73 | | names | Bucket name suffixes. | `list(string)` | n/a | yes | 74 | | prefix | Prefix used to generate the bucket name. | `string` | `""` | no | 75 | | project\_id | Bucket project id. | `string` | n/a | yes | 76 | | public\_access\_prevention | Prevents public access to a bucket. Acceptable values are inherited or enforced. If inherited, the bucket uses public access prevention, only if the bucket is subject to the public access prevention organization policy constraint. | `string` | `"inherited"` | no | 77 | | randomize\_suffix | Adds an identical, but randomized 4-character suffix to all bucket names | `bool` | `false` | no | 78 | | retention\_policy | Map of retention policy values. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket#retention_policy | `any` | `{}` | no | 79 | | set\_admin\_roles | Grant roles/storage.objectAdmin role to admins and bucket\_admins. | `bool` | `false` | no | 80 | | set\_creator\_roles | Grant roles/storage.objectCreator role to creators and bucket\_creators. | `bool` | `false` | no | 81 | | set\_hmac\_access | Set S3 compatible access to GCS. | `bool` | `false` | no | 82 | | set\_hmac\_key\_admin\_roles | Grant roles/storage.hmacKeyAdmin role to hmac\_key\_admins and bucket\_hmac\_key\_admins. | `bool` | `false` | no | 83 | | set\_storage\_admin\_roles | Grant roles/storage.admin role to storage\_admins and bucket\_storage\_admins. | `bool` | `false` | no | 84 | | set\_viewer\_roles | Grant roles/storage.objectViewer role to viewers and bucket\_viewers. | `bool` | `false` | no | 85 | | soft\_delete\_policy | Soft delete policies to apply. Map of lowercase unprefixed name => soft delete policy. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#nested_soft_delete_policy | `map(any)` | `{}` | no | 86 | | storage\_admins | IAM-style members who will be granted roles/storage.admin on all buckets. | `list(string)` | `[]` | no | 87 | | storage\_class | Bucket storage class. | `string` | `"STANDARD"` | no | 88 | | versioning | Optional map of lowercase unprefixed name => boolean, defaults to false. | `map(bool)` | `{}` | no | 89 | | viewers | IAM-style members who will be granted roles/storage.objectViewer on all buckets. | `list(string)` | `[]` | no | 90 | | website | Map of website values. Supported attributes: main\_page\_suffix, not\_found\_page |
object({
main_page_suffix = optional(string)
not_found_page = optional(string)
})
| `{}` | no | 91 | 92 | ## Outputs 93 | 94 | | Name | Description | 95 | |------|-------------| 96 | | apphub\_service\_uri | URI in CAIS style to be used by Apphub. | 97 | | bucket | Bucket resource (for single use). | 98 | | buckets | Bucket resources as list. | 99 | | buckets\_map | Bucket resources by name. | 100 | | hmac\_keys | List of HMAC keys. | 101 | | name | Bucket name (for single use). | 102 | | names | Bucket names. | 103 | | names\_list | List of bucket names. | 104 | | url | Bucket URL (for single use). | 105 | | urls | Bucket URLs. | 106 | | urls\_list | List of bucket URLs. | 107 | 108 | 109 | 110 | ## Requirements 111 | 112 | These sections describe requirements for using this module. 113 | 114 | ### Software 115 | 116 | The following dependencies must be available: 117 | 118 | - [Terraform](https://www.terraform.io/downloads.html) >= 0.13.0 119 | - For Terraform v0.11 see the [Compatibility](#compatibility) section above 120 | - [Terraform Provider for GCP][terraform-provider-gcp] plugin >= v4.42 121 | 122 | ### Service Account 123 | 124 | User or service account credentials with the following roles must be used to provision the resources of this module: 125 | 126 | - Storage Admin: `roles/storage.admin` 127 | 128 | The [Project Factory module][project-factory-module] and the 129 | [IAM module][iam-module] may be used in combination to provision a 130 | service account with the necessary roles applied. 131 | 132 | ### APIs 133 | 134 | A project with the following APIs enabled must be used to host the 135 | resources of this module: 136 | 137 | - Google Cloud Storage JSON API: `storage-api.googleapis.com` 138 | 139 | The [Project Factory module][project-factory-module] can be used to 140 | provision a project with the necessary APIs enabled. 141 | 142 | ## Contributing 143 | 144 | Refer to the [contribution guidelines](./CONTRIBUTING.md) for 145 | information on contributing to this module. 146 | 147 | [iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google 148 | [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google 149 | [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html 150 | [terraform]: https://www.terraform.io/downloads.html 151 | -------------------------------------------------------------------------------- /build/int.cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | timeout: 3600s 16 | steps: 17 | - id: swap-module-refs 18 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 19 | args: ['module-swapper'] 20 | - id: prepare 21 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 22 | args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && prepare_environment'] 23 | env: 24 | - 'TF_VAR_org_id=$_ORG_ID' 25 | - 'TF_VAR_folder_id=$_FOLDER_ID' 26 | - 'TF_VAR_billing_account=$_BILLING_ACCOUNT' 27 | - id: sleep 28 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 29 | args: ['/bin/bash', '-c', 'sleep 120'] 30 | - id: init 31 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 32 | args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose'] 33 | - id: apply 34 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 35 | args: ['/bin/bash', '-c', 'cft test run all --stage apply --verbose'] 36 | - id: verify 37 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 38 | args: ['/bin/bash', '-c', 'cft test run all --stage verify --verbose'] 39 | - id: destroy 40 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 41 | args: ['/bin/bash', '-c', 'cft test run all --stage destroy --verbose'] 42 | tags: 43 | - 'ci' 44 | - 'integration' 45 | substitutions: 46 | _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' 47 | _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.24' 48 | -------------------------------------------------------------------------------- /build/lint.cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | - id: 'lint-tests' 17 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 18 | args: ['/usr/local/bin/test_lint.sh'] 19 | tags: 20 | - 'ci' 21 | - 'lint' 22 | substitutions: 23 | _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' 24 | _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.24' 25 | -------------------------------------------------------------------------------- /docs/upgrading_to_v2.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v2.0 2 | 3 | The v2.0 release of the terraform-google-cloud-storage module is a backwards incompatible release, due to the following breaking changes: 4 | 5 | - The module now uses for_each instead of count. 6 | - The minimum Terraform version was increased to 0.13. 7 | 8 | ## Migration Instructions 9 | 10 | A migration from 1.x to 2.x as showcased below 11 | 12 | ```diff 13 | module "cloud_storage" { 14 | source = "terraform-google-modules/cloud-storage/google" 15 | - version = "1.7.2" 16 | + version = "~> 2.0" 17 | ``` 18 | will produce the following output during a `terraform plan`: 19 | 20 | ```bash 21 | module.cloud_storage.google_storage_bucket.buckets will be destroyed 22 | module.cloud_storage.google_storage_bucket.buckets[1] will be destroyed 23 | . 24 | . 25 | module.cloud_storage.google_storage_bucket.buckets["one"] 26 | module.cloud_storage.google_storage_bucket.buckets["two"] 27 | . 28 | . 29 | Plan: 2 to add, 0 to change, 2 to destroy. 30 | ``` 31 | 32 | To prevent bucket recreation, it is recommended to migrate the state locations using commands like this: 33 | 34 | ```shell 35 | terraform state mv module.cloud_storage.google_storage_bucket.buckets[0] 'module.cloud_storage.google_storage_bucket.buckets["one"]' 36 | terraform state mv module.cloud_storage.google_storage_bucket.buckets[1] 'module.cloud_storage.google_storage_bucket.buckets["two"]' 37 | ``` 38 | 39 | Re-running the plan should show that the storage bucket resources are no longer showing a diff. 40 | 41 | ``` 42 | Apply complete! Resources: 0 added, 0 changed, 0 destroyed. 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/upgrading_to_v4.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v4.0 2 | 3 | The v4.0 release of the terraform-google-cloud-storage module is a backwards incompatible release, due to the following breaking changes: 4 | 5 | - The bucket doesn't have location as mandatory part of the name prefix. 6 | - The minimum Terraform Google Provider version was increased to 4.42. 7 | 8 | ## Migration Instructions 9 | 10 | A migration from 3.x to 4.x as showcased below 11 | 12 | ```diff 13 | module "cloud_storage" { 14 | source = "terraform-google-modules/cloud-storage/google" 15 | - version = "~> 3.0" 16 | + version = "~> 4.0" 17 | ``` 18 | will produce the following output during a `terraform plan`: 19 | 20 | ```bash 21 | # module.cloud_storage.google_storage_bucket.buckets["one"] must be replaced 22 | ... 23 | ~ name = "multiple-buckets-iost-eu-one" -> "multiple-buckets-iost-one" # forces replacement 24 | ... 25 | # module.cloud_storage.google_storage_bucket.buckets["two"] must be replaced 26 | ... 27 | ~ name = "multiple-buckets-iost-eu-two" -> "multiple-buckets-iost-two" # forces replacement 28 | ... 29 | Plan: 2 to add, 0 to change, 2 to destroy. 30 | ``` 31 | 32 | In the module bucket prefix contained `location` before. To preserve the same bucket name with `location` in prefix you should make some code adjustments: 33 | 34 | ```diff 35 | - prefix = "multiple-buckets-${random_string.prefix.result}" 36 | + prefix = "multiple-buckets-${random_string.prefix.result}-eu" 37 | ``` 38 | 39 | Re-running the plan should show that the storage bucket resources are no longer showing a diff. 40 | 41 | ``` 42 | Apply complete! Resources: 0 added, 0 changed, 0 destroyed. 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/upgrading_to_v8.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v8.0 2 | 3 | The v8.0 release of the terraform-google-cloud-storage module is a backwards incompatible release, due to the following breaking change: 4 | 5 | - The fix for the issue [Error when using simple bucket with kms created in the same configuration](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/339) in the [Simple Bucket](../modules/simple_bucket/README.md) module replaced the creation of an internal KMS key based in the variable `encryption.default_kms_key_name` having a `null` value with an explicit control flag `internal_encryption_config.create_encryption_key`. 6 | 7 | ## Migration Instructions 8 | 9 | To migrate from 5.x or 6.0.0 no change is necessary for the Simple Bucket module. 10 | 11 | To migrate from 6.1.0 or 7.x: 12 | 13 | - If the feature to auto create KMS keys was not used no change is necessary for the Simple Bucket module 14 | - If the feature to auto create KMS keys was used, a migration from 7.x to 8.x for the Simple Bucket module as showcased below 15 | 16 | ```diff 17 | module "simple_bucket" { 18 | source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket" 19 | - version = "~> 7.0" 20 | + version = "~> 8.0" 21 | ``` 22 | 23 | will produce the following output during a `terraform plan`: 24 | 25 | ``` 26 | 27 | Error: Missing required argument 28 | 29 | with module.simple_bucket.google_storage_bucket.bucket, 30 | on .terraform/modules/simple_bucket/main.tf line 22, in resource "google_storage_bucket" "bucket": 31 | 22: resource "google_storage_bucket" "bucket" { 32 | 33 | The argument "encryption.0.default_kms_key_name" is required, but no definition was found. 34 | ``` 35 | 36 | Removing the `null` valued `encryption.default_kms_key_name` 37 | 38 | ```diff 39 | - -encryption = { 40 | - default_kms_key_name = null 41 | - } 42 | ``` 43 | 44 | will produce the following output during a `terraform plan`: 45 | 46 | ``` 47 | # module.simple_bucket.google_storage_bucket.bucket will be updated in-place 48 | 49 | # module.simple_bucket.module.encryption_key[0].google_kms_crypto_key.key_ephemeral[0] will be destroyed 50 | # (because module.simple_bucket.module.encryption_key[0] is not in configuration) 51 | 52 | # module.simple_bucket.module.encryption_key[0].google_kms_crypto_key_iam_binding.decrypters[0] will be destroyed 53 | # (because module.simple_bucket.module.encryption_key[0] is not in configuration) 54 | 55 | # module.simple_bucket.module.encryption_key[0].google_kms_crypto_key_iam_binding.encrypters[0] will be destroyed 56 | # (because module.simple_bucket.module.encryption_key[0] is not in configuration) 57 | 58 | # module.simple_bucket.module.encryption_key[0].google_kms_key_ring.key_ring will be destroyed 59 | # (because module.simple_bucket.module.encryption_key[0] is not in configuration) 60 | 61 | Plan: 0 to add, 1 to change, 4 to destroy. 62 | ``` 63 | 64 | To preserve the existing KMS Key, add the following section to your configuration 65 | 66 | ```diff 67 | + internal_encryption_config = { 68 | + create_encryption_key = true 69 | + } 70 | ``` 71 | 72 | Re-running the plan should show that the Simple Bucket resource is no longer showing a diff. 73 | 74 | ``` 75 | No changes. Your infrastructure matches the configuration. 76 | 77 | Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed. 78 | ``` 79 | -------------------------------------------------------------------------------- /docs/upgrading_to_v9.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to v9.0 2 | 3 | The v9.0 release contains backwards-incompatible changes. 4 | 5 | ## Replace uses of apphub_service_uri 6 | 7 | This release removes apphub_service_uri output. You can replace use of `apphub_service_uri` by forming the desired output as below, 8 | 9 | ``` 10 | { 11 | service_uri = "//storage.googleapis.com/${module.simple_bucket.name}" 12 | service_id = substr(module.simple_bucket.name, 0, 63) 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /examples/multiple_buckets/README.md: -------------------------------------------------------------------------------- 1 | # Simple Example 2 | 3 | This example illustrates how to use the `cloud-storage` module. 4 | 5 | 6 | ## Inputs 7 | 8 | | Name | Description | Type | Default | Required | 9 | |------|-------------|------|---------|:--------:| 10 | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | 11 | 12 | ## Outputs 13 | 14 | | Name | Description | 15 | |------|-------------| 16 | | names | Bucket names. | 17 | | names\_list | List of bucket names. | 18 | | project\_id | The ID of the project in which resources are provisioned. | 19 | 20 | 21 | 22 | To provision this example, run the following from within this directory: 23 | - `terraform init` to get the plugins 24 | - `terraform plan` to see the infrastructure plan 25 | - `terraform apply` to apply the infrastructure build 26 | - `terraform destroy` to destroy the built infrastructure 27 | -------------------------------------------------------------------------------- /examples/multiple_buckets/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | resource "random_string" "prefix" { 18 | length = 4 19 | upper = false 20 | special = false 21 | } 22 | 23 | module "cloud_storage" { 24 | source = "terraform-google-modules/cloud-storage/google" 25 | version = "~> 10.0" 26 | 27 | project_id = var.project_id 28 | 29 | prefix = "multiple-buckets-${random_string.prefix.result}" 30 | names = ["one", "two"] 31 | randomize_suffix = true 32 | 33 | bucket_policy_only = { 34 | "one" = true 35 | "two" = false 36 | } 37 | 38 | folders = { 39 | "two" = ["dev", "prod"] 40 | } 41 | 42 | lifecycle_rules = [ 43 | { 44 | action = { 45 | type = "SetStorageClass" 46 | storage_class = "NEARLINE" 47 | } 48 | condition = { 49 | age = "10" 50 | matches_storage_class = "MULTI_REGIONAL,STANDARD,DURABLE_REDUCED_AVAILABILITY" 51 | } 52 | } 53 | ] 54 | 55 | bucket_lifecycle_rules = { 56 | "one" = [ 57 | { 58 | action = { 59 | type = "Delete" 60 | } 61 | condition = { 62 | age = "90" 63 | } 64 | } 65 | ] 66 | } 67 | 68 | retention_policy = { 69 | "two" = { 70 | is_locked = false 71 | retention_period = 1 72 | } 73 | } 74 | 75 | default_event_based_hold = { 76 | "one" = true 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /examples/multiple_buckets/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "names" { 18 | description = "Bucket names." 19 | value = module.cloud_storage.names 20 | } 21 | 22 | output "names_list" { 23 | description = "List of bucket names." 24 | value = module.cloud_storage.names_list 25 | } 26 | 27 | output "project_id" { 28 | description = "The ID of the project in which resources are provisioned." 29 | value = var.project_id 30 | } 31 | -------------------------------------------------------------------------------- /examples/multiple_buckets/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | description = "The ID of the project in which to provision resources." 19 | type = string 20 | } 21 | -------------------------------------------------------------------------------- /examples/multiple_buckets/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 0.13" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | } 23 | random = { 24 | source = "hashicorp/random" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/simple_bucket/README.md: -------------------------------------------------------------------------------- 1 | # Simple Example 2 | 3 | This example illustrates how to use the `simple-bucket` submodule. 4 | 5 | 6 | ## Inputs 7 | 8 | | Name | Description | Type | Default | Required | 9 | |------|-------------|------|---------|:--------:| 10 | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | 11 | 12 | ## Outputs 13 | 14 | No outputs. 15 | 16 | 17 | 18 | To provision this example, run the following from within this directory: 19 | - `terraform init` to get the plugins 20 | - `terraform plan` to see the infrastructure plan 21 | - `terraform apply` to apply the infrastructure build 22 | - `terraform destroy` to destroy the built infrastructure 23 | -------------------------------------------------------------------------------- /examples/simple_bucket/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module "bucket" { 18 | source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket" 19 | version = "~> 10.0" 20 | 21 | name = "${var.project_id}-bucket" 22 | project_id = var.project_id 23 | location = "us" 24 | 25 | website = { 26 | main_page_suffix = "index.html" 27 | not_found_page = "404.html" 28 | } 29 | 30 | cors = [{ 31 | origin = ["http://image-store.com"] 32 | method = ["GET", "HEAD", "PUT", "POST", "DELETE"] 33 | response_header = ["*"] 34 | max_age_seconds = 3600 35 | }] 36 | 37 | lifecycle_rules = [{ 38 | action = { 39 | type = "Delete" 40 | } 41 | condition = { 42 | age = 365 43 | with_state = "ANY" 44 | matches_prefix = var.project_id 45 | } 46 | }] 47 | 48 | custom_placement_config = { 49 | data_locations : ["US-EAST4", "US-WEST1"] 50 | } 51 | 52 | iam_members = [{ 53 | role = "roles/storage.objectViewer" 54 | member = "group:test-gcp-ops@test.blueprints.joonix.net" 55 | }] 56 | 57 | autoclass = true 58 | retention_policy = { 59 | retention_period = 2 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/simple_bucket/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | description = "The ID of the project in which to provision resources." 19 | type = string 20 | } 21 | -------------------------------------------------------------------------------- /examples/simple_bucket/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /helpers/combine_docfiles.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Please note that this file was generated from 18 | # [terraform-google-module-template](https://github.com/terraform-google-modules/terraform-google-module-template). 19 | # Please make sure to contribute relevant changes upstream! 20 | 21 | ''' Combine file from: 22 | * script argument 1 23 | with content of file from: 24 | * script argument 2 25 | using the beginning of line separators 26 | hardcoded using regexes in this file: 27 | 28 | We exclude any text using the separate 29 | regex specified here 30 | ''' 31 | 32 | import os 33 | import re 34 | import sys 35 | 36 | insert_separator_regex = r'(.*?\[\^\]\:\ \(autogen_docs_start\))(.*?)(\n\[\^\]\:\ \(autogen_docs_end\).*?$)' # noqa: E501 37 | exclude_separator_regex = r'(.*?)Copyright 20\d\d Google LLC.*?limitations under the License.(.*?)$' # noqa: E501 38 | 39 | if len(sys.argv) != 3: 40 | sys.exit(1) 41 | 42 | if not os.path.isfile(sys.argv[1]): 43 | sys.exit(0) 44 | 45 | input = open(sys.argv[1], "r").read() 46 | replace_content = open(sys.argv[2], "r").read() 47 | 48 | # Exclude the specified content from the replacement content 49 | groups = re.match( 50 | exclude_separator_regex, 51 | replace_content, 52 | re.DOTALL 53 | ).groups(0) 54 | replace_content = groups[0] + groups[1] 55 | 56 | # Find where to put the replacement content, overwrite the input file 57 | match = re.match(insert_separator_regex, input, re.DOTALL) 58 | if match is None: 59 | print("ERROR: Could not find autogen docs anchors in", sys.argv[1]) 60 | print("To fix this, insert the following anchors in your README where " 61 | "module inputs and outputs should be documented.") 62 | print("[^]: (autogen_docs_start)") 63 | print("[^]: (autogen_docs_end)") 64 | sys.exit(1) 65 | groups = match.groups(0) 66 | output = groups[0] + replace_content + groups[2] + "\n" 67 | open(sys.argv[1], "w").write(output) 68 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /****************************************** 18 | Bucket random id suffix configuration 19 | *****************************************/ 20 | resource "random_id" "bucket_suffix" { 21 | count = var.randomize_suffix ? 1 : 0 22 | byte_length = 2 23 | } 24 | 25 | locals { 26 | suffix = var.randomize_suffix ? random_id.bucket_suffix[0].hex : "" 27 | names_set = toset(var.names) 28 | buckets_list = [for name in var.names : google_storage_bucket.buckets[name]] 29 | first_bucket = local.buckets_list[0] 30 | folder_list = flatten([ 31 | for bucket, folders in var.folders : [ 32 | for folder in folders : { 33 | bucket = bucket, 34 | folder = folder 35 | } 36 | ] 37 | ]) 38 | } 39 | 40 | resource "google_storage_bucket" "buckets" { 41 | for_each = local.names_set 42 | 43 | name = join("-", compact([var.prefix, each.value, local.suffix])) 44 | project = var.project_id 45 | location = var.location 46 | storage_class = var.storage_class 47 | labels = merge(var.labels, { name = replace(join("-", compact([var.prefix, each.value])), ".", "-") }) 48 | public_access_prevention = var.public_access_prevention 49 | 50 | force_destroy = lookup( 51 | var.force_destroy, 52 | lower(each.value), 53 | false, 54 | ) 55 | uniform_bucket_level_access = lookup( 56 | var.bucket_policy_only, 57 | lower(each.value), 58 | true, 59 | ) 60 | versioning { 61 | enabled = lookup( 62 | var.versioning, 63 | lower(each.value), 64 | false, 65 | ) 66 | } 67 | default_event_based_hold = lookup( 68 | var.default_event_based_hold, 69 | lower(each.value), 70 | false, 71 | ) 72 | autoclass { 73 | enabled = lookup( 74 | var.autoclass, 75 | lower(each.value), 76 | false, 77 | ) 78 | } 79 | hierarchical_namespace { 80 | enabled = lookup( 81 | var.hierarchical_namespace, 82 | lower(each.value), 83 | false, 84 | ) 85 | } 86 | # Having a permanent encryption block with default_kms_key_name = "" works but results in terraform applying a change every run 87 | # There is no enabled = false attribute available to ask terraform to ignore the block 88 | dynamic "encryption" { 89 | # If an encryption key name is set for this bucket name -> Create a single encryption block 90 | for_each = trimspace(lookup(var.encryption_key_names, lower(each.value), "")) != "" ? [true] : [] 91 | content { 92 | default_kms_key_name = trimspace( 93 | lookup( 94 | var.encryption_key_names, 95 | lower(each.value), 96 | "Error retrieving kms key name", # Should be unreachable due to the for_each check 97 | # Omitting default is deprecated & can help show if there was a bug 98 | # https://www.terraform.io/docs/configuration/functions/lookup.html 99 | ) 100 | ) 101 | } 102 | } 103 | dynamic "cors" { 104 | for_each = var.cors 105 | content { 106 | origin = lookup(cors.value, "origin", null) 107 | method = lookup(cors.value, "method", null) 108 | response_header = lookup(cors.value, "response_header", null) 109 | max_age_seconds = lookup(cors.value, "max_age_seconds", null) 110 | } 111 | } 112 | dynamic "website" { 113 | for_each = (var.website.main_page_suffix == null && var.website.not_found_page == null) ? toset([]) : toset([var.website]) 114 | content { 115 | main_page_suffix = lookup(website.value, "main_page_suffix", null) 116 | not_found_page = lookup(website.value, "not_found_page", null) 117 | } 118 | } 119 | 120 | dynamic "retention_policy" { 121 | for_each = lookup(var.retention_policy, each.value, null) != null ? [var.retention_policy[each.value]] : [] 122 | content { 123 | is_locked = lookup(retention_policy.value, "is_locked", null) 124 | retention_period = lookup(retention_policy.value, "retention_period", null) 125 | } 126 | } 127 | 128 | dynamic "custom_placement_config" { 129 | for_each = lookup(var.custom_placement_config, each.value, null) != null ? [var.custom_placement_config[each.value]] : [] 130 | content { 131 | data_locations = lookup(custom_placement_config.value, "data_locations", null) 132 | } 133 | } 134 | 135 | dynamic "lifecycle_rule" { 136 | for_each = setunion(var.lifecycle_rules, lookup(var.bucket_lifecycle_rules, each.value, toset([]))) 137 | content { 138 | action { 139 | type = lifecycle_rule.value.action.type 140 | storage_class = lookup(lifecycle_rule.value.action, "storage_class", null) 141 | } 142 | condition { 143 | age = lookup(lifecycle_rule.value.condition, "age", null) 144 | send_age_if_zero = lookup(lifecycle_rule.value.condition, "send_age_if_zero", null) 145 | created_before = lookup(lifecycle_rule.value.condition, "created_before", null) 146 | with_state = lookup(lifecycle_rule.value.condition, "with_state", contains(keys(lifecycle_rule.value.condition), "is_live") ? (lifecycle_rule.value.condition["is_live"] ? "LIVE" : null) : null) 147 | matches_storage_class = lifecycle_rule.value.condition["matches_storage_class"] != null ? split(",", lifecycle_rule.value.condition["matches_storage_class"]) : null 148 | matches_prefix = lifecycle_rule.value.condition["matches_prefix"] != null ? split(",", lifecycle_rule.value.condition["matches_prefix"]) : null 149 | matches_suffix = lifecycle_rule.value.condition["matches_suffix"] != null ? split(",", lifecycle_rule.value.condition["matches_suffix"]) : null 150 | num_newer_versions = lookup(lifecycle_rule.value.condition, "num_newer_versions", null) 151 | custom_time_before = lookup(lifecycle_rule.value.condition, "custom_time_before", null) 152 | days_since_custom_time = lookup(lifecycle_rule.value.condition, "days_since_custom_time", null) 153 | days_since_noncurrent_time = lookup(lifecycle_rule.value.condition, "days_since_noncurrent_time", null) 154 | noncurrent_time_before = lookup(lifecycle_rule.value.condition, "noncurrent_time_before", null) 155 | } 156 | } 157 | } 158 | 159 | dynamic "logging" { 160 | for_each = lookup(var.logging, each.value, null) != null ? { v = lookup(var.logging, each.value) } : {} 161 | content { 162 | log_bucket = lookup(logging.value, "log_bucket", null) 163 | log_object_prefix = lookup(logging.value, "log_object_prefix", null) 164 | } 165 | } 166 | 167 | dynamic "soft_delete_policy" { 168 | for_each = [lookup(var.soft_delete_policy, each.value, { 169 | retention_duration_seconds = null 170 | })] 171 | content { 172 | retention_duration_seconds = lookup(soft_delete_policy.value, "retention_duration_seconds", null) 173 | } 174 | } 175 | } 176 | 177 | resource "google_storage_bucket_iam_binding" "admins" { 178 | for_each = var.set_admin_roles ? local.names_set : [] 179 | bucket = google_storage_bucket.buckets[each.value].name 180 | role = "roles/storage.objectAdmin" 181 | members = compact( 182 | concat( 183 | var.admins, 184 | split( 185 | ",", 186 | lookup(var.bucket_admins, each.value, ""), 187 | ), 188 | ), 189 | ) 190 | } 191 | 192 | resource "google_storage_bucket_iam_binding" "creators" { 193 | for_each = var.set_creator_roles ? local.names_set : toset([]) 194 | bucket = google_storage_bucket.buckets[each.value].name 195 | role = "roles/storage.objectCreator" 196 | members = compact( 197 | concat( 198 | var.creators, 199 | split( 200 | ",", 201 | lookup(var.bucket_creators, each.value, ""), 202 | ), 203 | ), 204 | ) 205 | } 206 | 207 | resource "google_storage_bucket_iam_binding" "viewers" { 208 | for_each = var.set_viewer_roles ? local.names_set : toset([]) 209 | bucket = google_storage_bucket.buckets[each.value].name 210 | role = "roles/storage.objectViewer" 211 | members = compact( 212 | concat( 213 | var.viewers, 214 | split( 215 | ",", 216 | lookup(var.bucket_viewers, each.value, ""), 217 | ), 218 | ), 219 | ) 220 | } 221 | 222 | resource "google_storage_bucket_iam_binding" "hmac_key_admins" { 223 | for_each = var.set_hmac_key_admin_roles ? local.names_set : toset([]) 224 | bucket = google_storage_bucket.buckets[each.key].name 225 | role = "roles/storage.hmacKeyAdmin" 226 | members = compact( 227 | concat( 228 | var.hmac_key_admins, 229 | split( 230 | ",", 231 | lookup(var.bucket_hmac_key_admins, each.key, ""), 232 | ), 233 | ), 234 | ) 235 | } 236 | 237 | resource "google_storage_bucket_iam_binding" "storage_admins" { 238 | for_each = var.set_storage_admin_roles ? local.names_set : toset([]) 239 | bucket = google_storage_bucket.buckets[each.value].name 240 | role = "roles/storage.admin" 241 | members = compact( 242 | concat( 243 | var.storage_admins, 244 | split( 245 | ",", 246 | lookup(var.bucket_storage_admins, each.value, ""), 247 | ), 248 | ), 249 | ) 250 | } 251 | 252 | resource "google_storage_bucket_object" "folders" { 253 | for_each = { for obj in local.folder_list : "${obj.bucket}_${obj.folder}" => obj } 254 | bucket = google_storage_bucket.buckets[each.value.bucket].name 255 | name = "${each.value.folder}/" # Declaring an object with a trailing '/' creates a directory 256 | content = "foo" # Note that the content string isn't actually used, but is only there since the resource requires it 257 | } 258 | 259 | resource "google_storage_hmac_key" "hmac_keys" { 260 | project = var.project_id 261 | for_each = var.set_hmac_access ? var.hmac_service_accounts : {} 262 | service_account_email = each.key 263 | state = each.value 264 | } 265 | -------------------------------------------------------------------------------- /metadata.display.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-cloud-storage-display 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | info: 23 | title: Terraform Google Cloud Storage Module 24 | source: 25 | repo: https://github.com/terraform-google-modules/terraform-google-cloud-storage.git 26 | sourceType: git 27 | ui: 28 | input: 29 | variables: 30 | admins: 31 | name: admins 32 | title: Admins 33 | autoclass: 34 | name: autoclass 35 | title: Autoclass 36 | bucket_admins: 37 | name: bucket_admins 38 | title: Bucket Admins 39 | bucket_creators: 40 | name: bucket_creators 41 | title: Bucket Creators 42 | bucket_hmac_key_admins: 43 | name: bucket_hmac_key_admins 44 | title: Bucket Hmac Key Admins 45 | bucket_lifecycle_rules: 46 | name: bucket_lifecycle_rules 47 | title: Bucket Lifecycle Rules 48 | bucket_policy_only: 49 | name: bucket_policy_only 50 | title: Bucket Policy Only 51 | bucket_storage_admins: 52 | name: bucket_storage_admins 53 | title: Bucket Storage Admins 54 | bucket_viewers: 55 | name: bucket_viewers 56 | title: Bucket Viewers 57 | cors: 58 | name: cors 59 | title: Cors 60 | creators: 61 | name: creators 62 | title: Creators 63 | custom_placement_config: 64 | name: custom_placement_config 65 | title: Custom Placement Config 66 | default_event_based_hold: 67 | name: default_event_based_hold 68 | title: Default Event Based Hold 69 | encryption_key_names: 70 | name: encryption_key_names 71 | title: Encryption Key Names 72 | folders: 73 | name: folders 74 | title: Folders 75 | force_destroy: 76 | name: force_destroy 77 | title: Force Destroy 78 | hierarchical_namespace: 79 | name: hierarchical_namespace 80 | title: Hierarchical Namespace 81 | hmac_key_admins: 82 | name: hmac_key_admins 83 | title: Hmac Key Admins 84 | hmac_service_accounts: 85 | name: hmac_service_accounts 86 | title: Hmac Service Accounts 87 | labels: 88 | name: labels 89 | title: Labels 90 | lifecycle_rules: 91 | name: lifecycle_rules 92 | title: Lifecycle Rules 93 | location: 94 | name: location 95 | title: Location 96 | logging: 97 | name: logging 98 | title: Logging 99 | names: 100 | name: names 101 | title: Names 102 | prefix: 103 | name: prefix 104 | title: Prefix 105 | project_id: 106 | name: project_id 107 | title: Project Id 108 | public_access_prevention: 109 | name: public_access_prevention 110 | title: Public Access Prevention 111 | randomize_suffix: 112 | name: randomize_suffix 113 | title: Randomize Suffix 114 | retention_policy: 115 | name: retention_policy 116 | title: Retention Policy 117 | set_admin_roles: 118 | name: set_admin_roles 119 | title: Set Admin Roles 120 | set_creator_roles: 121 | name: set_creator_roles 122 | title: Set Creator Roles 123 | set_hmac_access: 124 | name: set_hmac_access 125 | title: Set Hmac Access 126 | set_hmac_key_admin_roles: 127 | name: set_hmac_key_admin_roles 128 | title: Set Hmac Key Admin Roles 129 | set_storage_admin_roles: 130 | name: set_storage_admin_roles 131 | title: Set Storage Admin Roles 132 | set_viewer_roles: 133 | name: set_viewer_roles 134 | title: Set Viewer Roles 135 | soft_delete_policy: 136 | name: soft_delete_policy 137 | title: Soft Delete Policy 138 | storage_admins: 139 | name: storage_admins 140 | title: Storage Admins 141 | storage_class: 142 | name: storage_class 143 | title: Storage Class 144 | versioning: 145 | name: versioning 146 | title: Versioning 147 | viewers: 148 | name: viewers 149 | title: Viewers 150 | website: 151 | name: website 152 | title: Website 153 | -------------------------------------------------------------------------------- /modules/simple_bucket/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Google Cloud Storage Module 2 | 3 | This module makes it easy to create a GCS bucket, and assign basic permissions on it to arbitrary users. 4 | 5 | The resources/services/activations/deletions that this module will create/trigger are: 6 | 7 | - One GCS bucket 8 | - Zero or more IAM bindings for that bucket 9 | 10 | ## Compatibility 11 | 12 | This module is meant for use with Terraform 0.13+. 13 | 14 | ## Usage 15 | 16 | Basic usage of this module is as follows: 17 | 18 | ```hcl 19 | module "bucket" { 20 | source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket" 21 | version = "~> 11.0" 22 | 23 | name = "example-bucket" 24 | project_id = "example-project" 25 | location = "us-east1" 26 | iam_members = [{ 27 | role = "roles/storage.objectViewer" 28 | member = "user:example-user@example.com" 29 | }] 30 | } 31 | ``` 32 | 33 | Functional examples are included in the 34 | [examples](../../examples/) directory. 35 | 36 | 37 | ## Inputs 38 | 39 | | Name | Description | Type | Default | Required | 40 | |------|-------------|------|---------|:--------:| 41 | | autoclass | While set to true, autoclass is enabled for this bucket. | `bool` | `false` | no | 42 | | bucket\_policy\_only | Enables Bucket Policy Only access to a bucket. | `bool` | `true` | no | 43 | | cors | Configuration of CORS for bucket with structure as defined in https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket#cors. |
list(object({
origin = optional(list(string))
method = optional(list(string))
response_header = optional(list(string))
max_age_seconds = optional(number)
}))
| `[]` | no | 44 | | custom\_placement\_config | Configuration of the bucket's custom location in a dual-region bucket setup. If the bucket is designated a single or multi-region, the variable are null. |
object({
data_locations = list(string)
})
| `null` | no | 45 | | encryption | A Cloud KMS key that will be used to encrypt objects inserted into this bucket. The key name should follow the format of `projects//locations//keyRings//cryptoKeys/`. To use a Cloud KMS key automatically created by this module use the `internal_encryption_config` input variable. |
object({
default_kms_key_name = string
})
| `null` | no | 46 | | force\_destroy | When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no | 47 | | hierarchical\_namespace | When set to true, hierarchical namespace is enable for this bucket. | `bool` | `false` | no | 48 | | iam\_members | The list of IAM members to grant permissions on the bucket. |
list(object({
role = string
member = string
}))
| `[]` | no | 49 | | internal\_encryption\_config | Configuration for the creation of an internal Google Cloud Key Management Service (KMS) Key for use as Customer-managed encryption key (CMEK) for the GCS Bucket
instead of creating one in advance and providing the key in the variable `encryption.default_kms_key_name`.
create\_encryption\_key: If `true` a Google Cloud Key Management Service (KMS) KeyRing and a Key will be created
prevent\_destroy: Set the prevent\_destroy lifecycle attribute on keys.
key\_destroy\_scheduled\_duration: Set the period of time that versions of keys spend in the `DESTROY_SCHEDULED` state before transitioning to `DESTROYED`.
key\_rotation\_period: Generate a new key every time this period passes. |
object({
create_encryption_key = optional(bool, false)
prevent_destroy = optional(bool, false)
key_destroy_scheduled_duration = optional(string, null)
key_rotation_period = optional(string, "7776000s")
})
| `{}` | no | 50 | | labels | A set of key/value label pairs to assign to the bucket. | `map(string)` | `null` | no | 51 | | lifecycle\_rules | The bucket's Lifecycle Rules configuration. |
list(object({
# Object with keys:
# - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass.
# - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule.
action = object({
type = string
storage_class = optional(string)
})

# Object with keys:
# - age - (Optional) Minimum age of an object in days to satisfy this condition.
# - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field.
# - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.
# - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY".
# - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY.
# - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition.
# - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition
# - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.
# - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition.
# - days_since_custom_time - (Optional) Days since the date set in the customTime metadata for the object.
# - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object.
# - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent.
condition = object({
age = optional(number)
send_age_if_zero = optional(bool)
created_before = optional(string)
with_state = optional(string)
matches_storage_class = optional(string)
matches_prefix = optional(string)
matches_suffix = optional(string)
num_newer_versions = optional(number)
custom_time_before = optional(string)
days_since_custom_time = optional(number)
days_since_noncurrent_time = optional(number)
noncurrent_time_before = optional(string)
})
}))
| `[]` | no | 52 | | location | The location of the bucket. See https://cloud.google.com/storage/docs/locations. | `string` | n/a | yes | 53 | | log\_bucket | The bucket that will receive log objects. | `string` | `null` | no | 54 | | log\_object\_prefix | The object prefix for log objects. If it's not provided, by default GCS sets this to this bucket's name | `string` | `null` | no | 55 | | name | The name of the bucket. | `string` | n/a | yes | 56 | | project\_id | The ID of the project to create the bucket in. | `string` | n/a | yes | 57 | | public\_access\_prevention | Prevents public access to a bucket. Acceptable values are inherited or enforced. If inherited, the bucket uses public access prevention, only if the bucket is subject to the public access prevention organization policy constraint. | `string` | `"inherited"` | no | 58 | | retention\_policy | Configuration of the bucket's data retention policy for how long objects in the bucket should be retained. |
object({
is_locked = optional(bool)
retention_period = number
})
| `null` | no | 59 | | soft\_delete\_policy | Soft delete policies to apply. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#nested_soft_delete_policy |
object({
retention_duration_seconds = optional(number)
})
| `{}` | no | 60 | | storage\_class | The Storage Class of the new bucket. | `string` | `null` | no | 61 | | versioning | While set to true, versioning is fully enabled for this bucket. | `bool` | `true` | no | 62 | | website | Map of website values. Supported attributes: main\_page\_suffix, not\_found\_page |
object({
main_page_suffix = optional(string)
not_found_page = optional(string)
})
| `{}` | no | 63 | 64 | ## Outputs 65 | 66 | | Name | Description | 67 | |------|-------------| 68 | | apphub\_service\_uri | URI in CAIS style to be used by Apphub. | 69 | | bucket | The created storage bucket | 70 | | internal\_kms\_configuration | The intenal KMS Resource. | 71 | | name | Bucket name. | 72 | | url | Bucket URL. | 73 | 74 | 75 | 76 | ## Requirements 77 | 78 | These sections describe requirements for using this module. 79 | 80 | ### Software 81 | 82 | The following dependencies must be available: 83 | 84 | - [Terraform][terraform] >= 0.13.0 85 | - [Terraform Provider for GCP][terraform-provider-gcp] plugin >= v4.42 86 | 87 | ### Service Account 88 | 89 | User or service account credentials with the following roles must be used to provision the resources of this module: 90 | 91 | - Storage Admin: `roles/storage.admin` 92 | 93 | The [Project Factory module][project-factory-module] and the 94 | [IAM module][iam-module] may be used in combination to provision a 95 | service account with the necessary roles applied. 96 | 97 | ### APIs 98 | 99 | A project with the following APIs enabled must be used to host the 100 | resources of this module: 101 | 102 | - Google Cloud Storage JSON API: `storage-api.googleapis.com` 103 | 104 | The [Project Factory module][project-factory-module] can be used to 105 | provision a project with the necessary APIs enabled. 106 | 107 | ## Contributing 108 | 109 | Refer to the [contribution guidelines](./CONTRIBUTING.md) for 110 | information on contributing to this module. 111 | 112 | [iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google 113 | [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google 114 | [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html 115 | [terraform]: https://www.terraform.io/downloads.html 116 | -------------------------------------------------------------------------------- /modules/simple_bucket/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | internal_encryption = var.internal_encryption_config.create_encryption_key ? { default_kms_key_name = module.encryption_key[0].keys[var.name] } : null 19 | encryption = var.internal_encryption_config.create_encryption_key ? local.internal_encryption : var.encryption 20 | } 21 | 22 | resource "google_storage_bucket" "bucket" { 23 | name = var.name 24 | project = var.project_id 25 | location = var.location 26 | storage_class = var.storage_class 27 | uniform_bucket_level_access = var.bucket_policy_only 28 | labels = var.labels 29 | force_destroy = var.force_destroy 30 | public_access_prevention = var.public_access_prevention 31 | 32 | versioning { 33 | enabled = var.versioning 34 | } 35 | 36 | autoclass { 37 | enabled = var.autoclass 38 | } 39 | 40 | hierarchical_namespace { 41 | enabled = var.hierarchical_namespace 42 | } 43 | 44 | dynamic "retention_policy" { 45 | for_each = var.retention_policy == null ? [] : [var.retention_policy] 46 | content { 47 | is_locked = var.retention_policy.is_locked 48 | retention_period = var.retention_policy.retention_period 49 | } 50 | } 51 | 52 | dynamic "encryption" { 53 | for_each = local.encryption == null ? [] : [local.encryption] 54 | content { 55 | default_kms_key_name = local.encryption.default_kms_key_name 56 | } 57 | } 58 | 59 | dynamic "website" { 60 | for_each = (var.website.main_page_suffix == null && var.website.not_found_page == null) ? toset([]) : toset([var.website]) 61 | content { 62 | main_page_suffix = lookup(website.value, "main_page_suffix", null) 63 | not_found_page = lookup(website.value, "not_found_page", null) 64 | } 65 | } 66 | 67 | dynamic "cors" { 68 | for_each = var.cors == null ? [] : var.cors 69 | content { 70 | origin = lookup(cors.value, "origin", null) 71 | method = lookup(cors.value, "method", null) 72 | response_header = lookup(cors.value, "response_header", null) 73 | max_age_seconds = lookup(cors.value, "max_age_seconds", null) 74 | } 75 | } 76 | 77 | dynamic "custom_placement_config" { 78 | for_each = var.custom_placement_config == null ? [] : [var.custom_placement_config] 79 | content { 80 | data_locations = var.custom_placement_config.data_locations 81 | } 82 | } 83 | 84 | dynamic "lifecycle_rule" { 85 | for_each = var.lifecycle_rules 86 | content { 87 | action { 88 | type = lifecycle_rule.value.action.type 89 | storage_class = lookup(lifecycle_rule.value.action, "storage_class", null) 90 | } 91 | condition { 92 | age = lookup(lifecycle_rule.value.condition, "age", null) 93 | send_age_if_zero = lookup(lifecycle_rule.value.condition, "send_age_if_zero", null) 94 | created_before = lookup(lifecycle_rule.value.condition, "created_before", null) 95 | with_state = lookup(lifecycle_rule.value.condition, "with_state", contains(keys(lifecycle_rule.value.condition), "is_live") ? (lifecycle_rule.value.condition["is_live"] ? "LIVE" : null) : null) 96 | matches_storage_class = lifecycle_rule.value.condition["matches_storage_class"] != null ? split(",", lifecycle_rule.value.condition["matches_storage_class"]) : null 97 | matches_prefix = lifecycle_rule.value.condition["matches_prefix"] != null ? split(",", lifecycle_rule.value.condition["matches_prefix"]) : null 98 | matches_suffix = lifecycle_rule.value.condition["matches_suffix"] != null ? split(",", lifecycle_rule.value.condition["matches_suffix"]) : null 99 | num_newer_versions = lookup(lifecycle_rule.value.condition, "num_newer_versions", null) 100 | custom_time_before = lookup(lifecycle_rule.value.condition, "custom_time_before", null) 101 | days_since_custom_time = lookup(lifecycle_rule.value.condition, "days_since_custom_time", null) 102 | days_since_noncurrent_time = lookup(lifecycle_rule.value.condition, "days_since_noncurrent_time", null) 103 | noncurrent_time_before = lookup(lifecycle_rule.value.condition, "noncurrent_time_before", null) 104 | } 105 | } 106 | } 107 | 108 | dynamic "logging" { 109 | for_each = var.log_bucket == null ? [] : [var.log_bucket] 110 | content { 111 | log_bucket = var.log_bucket 112 | log_object_prefix = var.log_object_prefix 113 | } 114 | } 115 | 116 | dynamic "soft_delete_policy" { 117 | for_each = var.soft_delete_policy == {} ? [] : [var.soft_delete_policy] 118 | content { 119 | retention_duration_seconds = lookup(soft_delete_policy.value, "retention_duration_seconds", null) 120 | } 121 | } 122 | } 123 | 124 | resource "google_storage_bucket_iam_member" "members" { 125 | for_each = { 126 | for m in var.iam_members : "${m.role} ${m.member}" => m 127 | } 128 | bucket = google_storage_bucket.bucket.name 129 | role = each.value.role 130 | member = each.value.member 131 | } 132 | 133 | data "google_storage_project_service_account" "gcs_account" { 134 | project = var.project_id 135 | } 136 | 137 | module "encryption_key" { 138 | source = "terraform-google-modules/kms/google" 139 | version = "~> 4.0" 140 | count = var.internal_encryption_config.create_encryption_key ? 1 : 0 141 | 142 | project_id = var.project_id 143 | location = lower(var.location) 144 | keyring = var.name 145 | prevent_destroy = var.internal_encryption_config.prevent_destroy 146 | key_destroy_scheduled_duration = var.internal_encryption_config.key_destroy_scheduled_duration 147 | key_rotation_period = var.internal_encryption_config.key_rotation_period 148 | keys = [var.name] 149 | set_decrypters_for = [var.name] 150 | set_encrypters_for = [var.name] 151 | decrypters = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"] 152 | encrypters = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"] 153 | } 154 | -------------------------------------------------------------------------------- /modules/simple_bucket/metadata.display.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-cloud-storage-display 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | info: 23 | title: Terraform Google Cloud Storage Module 24 | source: 25 | repo: https://github.com/terraform-google-modules/terraform-google-cloud-storage.git 26 | sourceType: git 27 | dir: /modules/simple_bucket 28 | ui: 29 | input: 30 | variables: 31 | autoclass: 32 | name: autoclass 33 | title: Autoclass 34 | level: 1 35 | bucket_policy_only: 36 | name: bucket_policy_only 37 | title: Bucket Policy Only 38 | level: 1 39 | cors: 40 | name: cors 41 | title: Cors 42 | custom_placement_config: 43 | name: custom_placement_config 44 | title: Custom Placement Config 45 | encryption: 46 | name: encryption 47 | title: Encryption 48 | level: 1 49 | force_destroy: 50 | name: force_destroy 51 | title: Force Destroy 52 | invisible: false 53 | hierarchical_namespace: 54 | name: hierarchical_namespace 55 | title: Hierarchical Namespace 56 | iam_members: 57 | name: iam_members 58 | title: Iam Members 59 | internal_encryption_config: 60 | name: internal_encryption_config 61 | title: Internal Encryption Config 62 | level: 1 63 | labels: 64 | name: labels 65 | title: Labels 66 | lifecycle_rules: 67 | name: lifecycle_rules 68 | title: Lifecycle Rules 69 | level: 1 70 | location: 71 | name: location 72 | title: Location 73 | log_bucket: 74 | name: log_bucket 75 | title: Log Bucket 76 | log_object_prefix: 77 | name: log_object_prefix 78 | title: Log Object Prefix 79 | name: 80 | name: name 81 | title: Name 82 | regexValidation: ^[a-z0-9][a-z0-9-_.]{2,61}[a-z0-9]$ 83 | validation: Use lowercase letters, numbers,underscores, periods and hyphens. Start with a letter/number and end with letter/number. Must be between 3 and 63 characters. 84 | project_id: 85 | name: project_id 86 | title: Project Id 87 | public_access_prevention: 88 | name: public_access_prevention 89 | title: Public Access Prevention 90 | retention_policy: 91 | name: retention_policy 92 | title: Retention Policy 93 | level: 1 94 | soft_delete_policy: 95 | name: soft_delete_policy 96 | title: Soft Delete Policy 97 | storage_class: 98 | name: storage_class 99 | title: Storage Class 100 | enumValueLabels: 101 | - label: STANDARD 102 | value: STANDARD 103 | - label: MULTI_REGIONAL 104 | value: MULTI_REGIONAL 105 | - label: REGIONAL 106 | value: REGIONAL 107 | - label: NEARLINE 108 | value: NEARLINE 109 | - label: COLDLINE 110 | value: COLDLINE 111 | - label: ARCHIVE 112 | value: ARCHIVE 113 | level: 1 114 | altDefaults: 115 | - type: ALTERNATE_TYPE_DC 116 | value: STANDARD 117 | versioning: 118 | name: versioning 119 | title: Versioning 120 | level: 1 121 | website: 122 | name: website 123 | title: Website 124 | -------------------------------------------------------------------------------- /modules/simple_bucket/metadata.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-cloud-storage 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | info: 23 | title: Terraform Google Cloud Storage Module 24 | source: 25 | repo: https://github.com/terraform-google-modules/terraform-google-cloud-storage.git 26 | sourceType: git 27 | dir: /modules/simple_bucket 28 | version: 11.0.0 29 | actuationTool: 30 | flavor: Terraform 31 | version: ">= 0.13" 32 | description: {} 33 | content: 34 | examples: 35 | - name: multiple_buckets 36 | location: examples/multiple_buckets 37 | - name: simple_bucket 38 | location: examples/simple_bucket 39 | interfaces: 40 | variables: 41 | - name: project_id 42 | description: The ID of the project to create the bucket in. 43 | varType: string 44 | required: true 45 | - name: location 46 | description: The location of the bucket. See https://cloud.google.com/storage/docs/locations. 47 | varType: string 48 | required: true 49 | - name: name 50 | description: The name of the bucket. 51 | varType: string 52 | required: true 53 | - name: force_destroy 54 | description: When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. 55 | varType: bool 56 | defaultValue: false 57 | - name: iam_members 58 | description: The list of IAM members to grant permissions on the bucket. 59 | varType: |- 60 | list(object({ 61 | role = string 62 | member = string 63 | })) 64 | defaultValue: [] 65 | connections: 66 | - source: 67 | source: github.com/GoogleCloudPlatform/terraform-google-cloud-run//modules/v2 68 | version: ">= 0.13" 69 | spec: 70 | outputExpr: "{\"member\": service_account_id.member, \"role\": \"roles/storage.objectAdmin\"}" 71 | - source: 72 | source: github.com/terraform-google-modules/terraform-google-vm//modules/instance_template 73 | version: ">= 13.2.0" 74 | spec: 75 | outputExpr: "{\"member\": service_account_info.member, \"role\": \"roles/storage.objectAdmin\"}" 76 | - source: 77 | source: github.com/terraform-google-modules/terraform-google-service-accounts//modules/simple-sa 78 | version: ">= 4.4" 79 | spec: 80 | outputExpr: "{\"member\": iam_email, \"role\": \"roles/storage.objectAdmin\"}" 81 | - name: storage_class 82 | description: The Storage Class of the new bucket. 83 | varType: string 84 | - name: labels 85 | description: A set of key/value label pairs to assign to the bucket. 86 | varType: map(string) 87 | - name: bucket_policy_only 88 | description: Enables Bucket Policy Only access to a bucket. 89 | varType: bool 90 | defaultValue: true 91 | - name: versioning 92 | description: While set to true, versioning is fully enabled for this bucket. 93 | varType: bool 94 | defaultValue: true 95 | - name: autoclass 96 | description: While set to true, autoclass is enabled for this bucket. 97 | varType: bool 98 | defaultValue: false 99 | - name: hierarchical_namespace 100 | description: While set to true, hierarchical namespace is enabled for this bucket. 101 | varType: bool 102 | defaultValue: false 103 | - name: retention_policy 104 | description: Configuration of the bucket's data retention policy for how long objects in the bucket should be retained. 105 | varType: |- 106 | object({ 107 | is_locked = optional(bool) 108 | retention_period = number 109 | }) 110 | - name: custom_placement_config 111 | description: Configuration of the bucket's custom location in a dual-region bucket setup. If the bucket is designated a single or multi-region, the variable are null. 112 | varType: |- 113 | object({ 114 | data_locations = list(string) 115 | }) 116 | - name: cors 117 | description: Configuration of CORS for bucket with structure as defined in https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket#cors. 118 | varType: |- 119 | list(object({ 120 | origin = optional(list(string)) 121 | method = optional(list(string)) 122 | response_header = optional(list(string)) 123 | max_age_seconds = optional(number) 124 | })) 125 | defaultValue: [] 126 | - name: encryption 127 | description: A Cloud KMS key that will be used to encrypt objects inserted into this bucket. The key name should follow the format of `projects//locations//keyRings//cryptoKeys/`. To use a Cloud KMS key automatically created by this module use the `internal_encryption_config` input variable. 128 | varType: |- 129 | object({ 130 | default_kms_key_name = string 131 | }) 132 | - name: lifecycle_rules 133 | description: The bucket's Lifecycle Rules configuration. 134 | varType: |- 135 | list(object({ 136 | # Object with keys: 137 | # - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass. 138 | # - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule. 139 | action = object({ 140 | type = string 141 | storage_class = optional(string) 142 | }) 143 | 144 | # Object with keys: 145 | # - age - (Optional) Minimum age of an object in days to satisfy this condition. 146 | # - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field. 147 | # - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition. 148 | # - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY". 149 | # - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY. 150 | # - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition. 151 | # - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition 152 | # - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition. 153 | # - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition. 154 | # - days_since_custom_time - (Optional) Days since the date set in the customTime metadata for the object. 155 | # - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object. 156 | # - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent. 157 | condition = object({ 158 | age = optional(number) 159 | send_age_if_zero = optional(bool) 160 | created_before = optional(string) 161 | with_state = optional(string) 162 | matches_storage_class = optional(string) 163 | matches_prefix = optional(string) 164 | matches_suffix = optional(string) 165 | num_newer_versions = optional(number) 166 | custom_time_before = optional(string) 167 | days_since_custom_time = optional(number) 168 | days_since_noncurrent_time = optional(number) 169 | noncurrent_time_before = optional(string) 170 | }) 171 | })) 172 | defaultValue: [] 173 | - name: log_bucket 174 | description: The bucket that will receive log objects. 175 | varType: string 176 | - name: log_object_prefix 177 | description: The object prefix for log objects. If it's not provided, by default GCS sets this to this bucket's name 178 | varType: string 179 | - name: website 180 | description: "Map of website values. Supported attributes: main_page_suffix, not_found_page" 181 | varType: |- 182 | object({ 183 | main_page_suffix = optional(string) 184 | not_found_page = optional(string) 185 | }) 186 | defaultValue: {} 187 | - name: public_access_prevention 188 | description: Prevents public access to a bucket. Acceptable values are inherited or enforced. If inherited, the bucket uses public access prevention, only if the bucket is subject to the public access prevention organization policy constraint. 189 | varType: string 190 | defaultValue: inherited 191 | - name: soft_delete_policy 192 | description: Soft delete policies to apply. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#nested_soft_delete_policy 193 | varType: |- 194 | object({ 195 | retention_duration_seconds = optional(number) 196 | }) 197 | defaultValue: {} 198 | - name: internal_encryption_config 199 | description: " Configuration for the creation of an internal Google Cloud Key Management Service (KMS) Key for use as Customer-managed encryption key (CMEK) for the GCS Bucket\n instead of creating one in advance and providing the key in the variable `encryption.default_kms_key_name`.\n create_encryption_key: If `true` a Google Cloud Key Management Service (KMS) KeyRing and a Key will be created\n prevent_destroy: Set the prevent_destroy lifecycle attribute on keys.\n key_destroy_scheduled_duration: Set the period of time that versions of keys spend in the `DESTROY_SCHEDULED` state before transitioning to `DESTROYED`.\n key_rotation_period: Generate a new key every time this period passes.\n" 200 | varType: |- 201 | object({ 202 | create_encryption_key = optional(bool, false) 203 | prevent_destroy = optional(bool, false) 204 | key_destroy_scheduled_duration = optional(string, null) 205 | key_rotation_period = optional(string, "7776000s") 206 | }) 207 | defaultValue: {} 208 | outputs: 209 | - name: apphub_service_uri 210 | description: URI in CAIS style to be used by Apphub. 211 | type: 212 | - object 213 | - location: string 214 | service_id: string 215 | service_uri: string 216 | - name: bucket 217 | description: The created storage bucket 218 | type: 219 | - object 220 | - autoclass: 221 | - list 222 | - - object 223 | - enabled: bool 224 | terminal_storage_class: string 225 | cors: 226 | - list 227 | - - object 228 | - max_age_seconds: number 229 | method: 230 | - list 231 | - string 232 | origin: 233 | - list 234 | - string 235 | response_header: 236 | - list 237 | - string 238 | custom_placement_config: 239 | - list 240 | - - object 241 | - data_locations: 242 | - set 243 | - string 244 | default_event_based_hold: bool 245 | effective_labels: 246 | - map 247 | - string 248 | enable_object_retention: bool 249 | encryption: 250 | - list 251 | - - object 252 | - default_kms_key_name: string 253 | force_destroy: bool 254 | hierarchical_namespace: 255 | - list 256 | - - object 257 | - enabled: bool 258 | terminal_storage_class: string 259 | id: string 260 | labels: 261 | - map 262 | - string 263 | lifecycle_rule: 264 | - list 265 | - - object 266 | - action: 267 | - set 268 | - - object 269 | - storage_class: string 270 | type: string 271 | condition: 272 | - set 273 | - - object 274 | - age: number 275 | created_before: string 276 | custom_time_before: string 277 | days_since_custom_time: number 278 | days_since_noncurrent_time: number 279 | matches_prefix: 280 | - list 281 | - string 282 | matches_storage_class: 283 | - list 284 | - string 285 | matches_suffix: 286 | - list 287 | - string 288 | no_age: bool 289 | noncurrent_time_before: string 290 | num_newer_versions: number 291 | send_age_if_zero: bool 292 | send_days_since_custom_time_if_zero: bool 293 | send_days_since_noncurrent_time_if_zero: bool 294 | send_num_newer_versions_if_zero: bool 295 | with_state: string 296 | location: string 297 | logging: 298 | - list 299 | - - object 300 | - log_bucket: string 301 | log_object_prefix: string 302 | name: string 303 | project: string 304 | project_number: number 305 | public_access_prevention: string 306 | requester_pays: bool 307 | retention_policy: 308 | - list 309 | - - object 310 | - is_locked: bool 311 | retention_period: number 312 | rpo: string 313 | self_link: string 314 | soft_delete_policy: 315 | - list 316 | - - object 317 | - effective_time: string 318 | retention_duration_seconds: number 319 | storage_class: string 320 | terraform_labels: 321 | - map 322 | - string 323 | timeouts: 324 | - object 325 | - create: string 326 | read: string 327 | update: string 328 | uniform_bucket_level_access: bool 329 | url: string 330 | versioning: 331 | - list 332 | - - object 333 | - enabled: bool 334 | website: 335 | - list 336 | - - object 337 | - main_page_suffix: string 338 | not_found_page: string 339 | - name: internal_kms_configuration 340 | description: The intenal KMS Resource. 341 | type: 342 | - object 343 | - keyring: string 344 | - name: name 345 | description: Bucket name. 346 | type: string 347 | - name: url 348 | description: Bucket URL. 349 | type: string 350 | requirements: 351 | roles: 352 | - level: Project 353 | roles: 354 | - roles/cloudkms.cryptoKeyEncrypterDecrypter 355 | - roles/iam.serviceAccountUser 356 | - roles/storage.admin 357 | services: 358 | - cloudkms.googleapis.com 359 | - cloudresourcemanager.googleapis.com 360 | - compute.googleapis.com 361 | - iam.googleapis.com 362 | - serviceusage.googleapis.com 363 | - storage-api.googleapis.com 364 | providerVersions: 365 | - source: hashicorp/google 366 | version: ">= 5.43.0, < 7" 367 | -------------------------------------------------------------------------------- /modules/simple_bucket/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "bucket" { 18 | description = "The created storage bucket" 19 | value = google_storage_bucket.bucket 20 | } 21 | 22 | output "name" { 23 | description = "Bucket name." 24 | value = google_storage_bucket.bucket.name 25 | } 26 | 27 | output "url" { 28 | description = "Bucket URL." 29 | value = google_storage_bucket.bucket.url 30 | } 31 | 32 | output "internal_kms_configuration" { 33 | description = "The intenal KMS Resource." 34 | value = var.internal_encryption_config.create_encryption_key ? module.encryption_key[0] : null 35 | } 36 | 37 | output "apphub_service_uri" { 38 | value = { 39 | service_uri = "//storage.googleapis.com/${element(split("//", google_storage_bucket.bucket.url), 1)}" 40 | service_id = substr(google_storage_bucket.bucket.name, 0, 63) 41 | location = var.location 42 | } 43 | description = "URI in CAIS style to be used by Apphub." 44 | } 45 | -------------------------------------------------------------------------------- /modules/simple_bucket/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | description = "The ID of the project to create the bucket in." 19 | type = string 20 | } 21 | 22 | variable "location" { 23 | description = "The location of the bucket. See https://cloud.google.com/storage/docs/locations." 24 | type = string 25 | } 26 | 27 | variable "name" { 28 | description = "The name of the bucket." 29 | type = string 30 | } 31 | 32 | variable "force_destroy" { 33 | description = "When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects." 34 | type = bool 35 | default = false 36 | } 37 | 38 | variable "iam_members" { 39 | description = "The list of IAM members to grant permissions on the bucket." 40 | type = list(object({ 41 | role = string 42 | member = string 43 | })) 44 | default = [] 45 | } 46 | 47 | variable "storage_class" { 48 | description = "The Storage Class of the new bucket." 49 | type = string 50 | default = null 51 | } 52 | 53 | variable "labels" { 54 | description = "A set of key/value label pairs to assign to the bucket." 55 | type = map(string) 56 | default = null 57 | } 58 | 59 | 60 | variable "bucket_policy_only" { 61 | description = "Enables Bucket Policy Only access to a bucket." 62 | type = bool 63 | default = true 64 | } 65 | 66 | variable "versioning" { 67 | description = "While set to true, versioning is fully enabled for this bucket." 68 | type = bool 69 | default = true 70 | } 71 | 72 | variable "autoclass" { 73 | description = "While set to true, autoclass is enabled for this bucket." 74 | type = bool 75 | default = false 76 | } 77 | 78 | variable "hierarchical_namespace" { 79 | description = "When set to true, hierarchical namespace is enable for this bucket." 80 | type = bool 81 | default = false 82 | } 83 | 84 | variable "retention_policy" { 85 | description = "Configuration of the bucket's data retention policy for how long objects in the bucket should be retained." 86 | type = object({ 87 | is_locked = optional(bool) 88 | retention_period = number 89 | }) 90 | default = null 91 | } 92 | 93 | variable "custom_placement_config" { 94 | description = "Configuration of the bucket's custom location in a dual-region bucket setup. If the bucket is designated a single or multi-region, the variable are null." 95 | type = object({ 96 | data_locations = list(string) 97 | }) 98 | default = null 99 | } 100 | 101 | variable "cors" { 102 | description = "Configuration of CORS for bucket with structure as defined in https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket#cors." 103 | type = list(object({ 104 | origin = optional(list(string)) 105 | method = optional(list(string)) 106 | response_header = optional(list(string)) 107 | max_age_seconds = optional(number) 108 | })) 109 | default = [] 110 | } 111 | 112 | variable "encryption" { 113 | description = "A Cloud KMS key that will be used to encrypt objects inserted into this bucket. The key name should follow the format of `projects//locations//keyRings//cryptoKeys/`. To use a Cloud KMS key automatically created by this module use the `internal_encryption_config` input variable." 114 | type = object({ 115 | default_kms_key_name = string 116 | }) 117 | default = null 118 | } 119 | 120 | variable "lifecycle_rules" { 121 | description = "The bucket's Lifecycle Rules configuration." 122 | type = list(object({ 123 | # Object with keys: 124 | # - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass. 125 | # - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule. 126 | action = object({ 127 | type = string 128 | storage_class = optional(string) 129 | }) 130 | 131 | # Object with keys: 132 | # - age - (Optional) Minimum age of an object in days to satisfy this condition. 133 | # - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field. 134 | # - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition. 135 | # - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY". 136 | # - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY. 137 | # - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition. 138 | # - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition 139 | # - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition. 140 | # - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition. 141 | # - days_since_custom_time - (Optional) Days since the date set in the customTime metadata for the object. 142 | # - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object. 143 | # - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent. 144 | condition = object({ 145 | age = optional(number) 146 | send_age_if_zero = optional(bool) 147 | created_before = optional(string) 148 | with_state = optional(string) 149 | matches_storage_class = optional(string) 150 | matches_prefix = optional(string) 151 | matches_suffix = optional(string) 152 | num_newer_versions = optional(number) 153 | custom_time_before = optional(string) 154 | days_since_custom_time = optional(number) 155 | days_since_noncurrent_time = optional(number) 156 | noncurrent_time_before = optional(string) 157 | }) 158 | })) 159 | default = [] 160 | } 161 | 162 | variable "log_bucket" { 163 | description = "The bucket that will receive log objects." 164 | type = string 165 | default = null 166 | } 167 | 168 | variable "log_object_prefix" { 169 | description = "The object prefix for log objects. If it's not provided, by default GCS sets this to this bucket's name" 170 | type = string 171 | default = null 172 | } 173 | 174 | variable "website" { 175 | type = object({ 176 | main_page_suffix = optional(string) 177 | not_found_page = optional(string) 178 | }) 179 | default = {} 180 | description = "Map of website values. Supported attributes: main_page_suffix, not_found_page" 181 | } 182 | 183 | variable "public_access_prevention" { 184 | description = "Prevents public access to a bucket. Acceptable values are inherited or enforced. If inherited, the bucket uses public access prevention, only if the bucket is subject to the public access prevention organization policy constraint." 185 | type = string 186 | default = "inherited" 187 | } 188 | 189 | variable "soft_delete_policy" { 190 | description = "Soft delete policies to apply. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#nested_soft_delete_policy" 191 | type = object({ 192 | retention_duration_seconds = optional(number) 193 | }) 194 | default = {} 195 | } 196 | 197 | variable "internal_encryption_config" { 198 | description = < bucket.name 46 | } 47 | } 48 | 49 | output "urls" { 50 | description = "Bucket URLs." 51 | value = { for name, bucket in google_storage_bucket.buckets : 52 | name => bucket.url 53 | } 54 | } 55 | 56 | output "names_list" { 57 | description = "List of bucket names." 58 | value = local.buckets_list[*].name 59 | } 60 | 61 | output "urls_list" { 62 | description = "List of bucket URLs." 63 | value = local.buckets_list[*].url 64 | } 65 | 66 | output "hmac_keys" { 67 | description = "List of HMAC keys." 68 | value = google_storage_hmac_key.hmac_keys[*] 69 | sensitive = true 70 | } 71 | 72 | output "apphub_service_uri" { 73 | value = [for bucket in local.buckets_list : { 74 | service_uri = "//storage.googleapis.com/${bucket.name}" 75 | service_id = substr(bucket.name, 0, 63) 76 | }] 77 | description = "URI in CAIS style to be used by Apphub." 78 | } 79 | -------------------------------------------------------------------------------- /test/integration/discover_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package test 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 21 | ) 22 | 23 | func TestAll(t *testing.T) { 24 | tft.AutoDiscoverAndTest(t) 25 | } 26 | -------------------------------------------------------------------------------- /test/integration/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/terraform-google-modules/terraform-google-cloud-storage/test/integration 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.23.9 6 | 7 | require ( 8 | github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.6 9 | github.com/gruntwork-io/terratest v0.49.0 10 | github.com/stretchr/testify v1.10.0 11 | ) 12 | 13 | require ( 14 | cloud.google.com/go v0.116.0 // indirect 15 | cloud.google.com/go/compute v1.28.3 // indirect 16 | cloud.google.com/go/compute/metadata v0.5.2 // indirect 17 | cloud.google.com/go/iam v1.2.2 // indirect 18 | cloud.google.com/go/storage v1.47.0 // indirect 19 | github.com/agext/levenshtein v1.2.3 // indirect 20 | github.com/alexflint/go-filemutex v1.3.0 // indirect 21 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 22 | github.com/aws/aws-sdk-go v1.45.5 // indirect 23 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 24 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 25 | github.com/go-errors/errors v1.5.0 // indirect 26 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 27 | github.com/go-openapi/jsonreference v0.20.2 // indirect 28 | github.com/go-openapi/swag v0.23.0 // indirect 29 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 30 | github.com/golang/protobuf v1.5.4 // indirect 31 | github.com/google/gnostic-models v0.6.9 // indirect 32 | github.com/google/go-cmp v0.6.0 // indirect 33 | github.com/google/s2a-go v0.1.8 // indirect 34 | github.com/google/uuid v1.6.0 // indirect 35 | github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect 36 | github.com/googleapis/gax-go/v2 v2.14.0 // indirect 37 | github.com/hashicorp/errwrap v1.1.0 // indirect 38 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 39 | github.com/hashicorp/go-getter v1.7.6 // indirect 40 | github.com/hashicorp/go-getter/v2 v2.2.3 // indirect 41 | github.com/hashicorp/go-multierror v1.1.1 // indirect 42 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 43 | github.com/hashicorp/go-version v1.7.0 // indirect 44 | github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f // indirect 45 | github.com/hashicorp/hcl/v2 v2.22.0 // indirect 46 | github.com/hashicorp/terraform-config-inspect v0.0.0-20250203082807-efaa306e97b4 // indirect 47 | github.com/hashicorp/terraform-json v0.24.0 // indirect 48 | github.com/jinzhu/copier v0.4.0 // indirect 49 | github.com/jmespath/go-jmespath v0.4.0 // indirect 50 | github.com/josharian/intern v1.0.0 // indirect 51 | github.com/klauspost/compress v1.16.7 // indirect 52 | github.com/mailru/easyjson v0.7.7 // indirect 53 | github.com/mattn/go-shellwords v1.0.12 // indirect 54 | github.com/mattn/go-zglob v0.0.4 // indirect 55 | github.com/mitchellh/go-homedir v1.1.0 // indirect 56 | github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 // indirect 57 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 58 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 59 | github.com/tidwall/gjson v1.18.0 // indirect 60 | github.com/tidwall/match v1.1.1 // indirect 61 | github.com/tidwall/pretty v1.2.1 // indirect 62 | github.com/tidwall/sjson v1.2.5 // indirect 63 | github.com/tmccombs/hcl2json v0.6.4 // indirect 64 | github.com/ulikunitz/xz v0.5.11 // indirect 65 | github.com/zclconf/go-cty v1.15.1 // indirect 66 | go.opencensus.io v0.24.0 // indirect 67 | golang.org/x/crypto v0.36.0 // indirect 68 | golang.org/x/mod v0.23.0 // indirect 69 | golang.org/x/net v0.38.0 // indirect 70 | golang.org/x/oauth2 v0.24.0 // indirect 71 | golang.org/x/sync v0.12.0 // indirect 72 | golang.org/x/sys v0.31.0 // indirect 73 | golang.org/x/text v0.23.0 // indirect 74 | golang.org/x/tools v0.26.0 // indirect 75 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect 76 | google.golang.org/api v0.206.0 // indirect 77 | google.golang.org/appengine v1.6.8 // indirect 78 | google.golang.org/genproto v0.0.0-20241113202542-65e8d215514f // indirect 79 | google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect 80 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect 81 | google.golang.org/grpc v1.67.1 // indirect 82 | google.golang.org/protobuf v1.35.1 // indirect 83 | gopkg.in/yaml.v3 v3.0.1 // indirect 84 | k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect 85 | sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect 86 | sigs.k8s.io/yaml v1.4.0 // indirect 87 | ) 88 | -------------------------------------------------------------------------------- /test/integration/multiple_buckets/multiple_buckets_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package multiple_buckets 16 | 17 | import ( 18 | "fmt" 19 | "strings" 20 | "testing" 21 | "time" 22 | 23 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" 24 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 25 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils" 26 | "github.com/gruntwork-io/terratest/modules/terraform" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | // Retry if these errors are encountered. 31 | var retryErrors = map[string]string{ 32 | // https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/204 33 | ".*Provider produced inconsistent final plan.*": "Provider bug, retry", 34 | } 35 | 36 | func TestMultipleBuckets(t *testing.T) { 37 | buckets := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(retryErrors, 5, time.Minute)) 38 | 39 | buckets.DefineVerify(func(assert *assert.Assertions) { 40 | buckets.DefaultVerify(assert) 41 | 42 | projectID := buckets.GetStringOutput("project_id") 43 | names := terraform.OutputList(t, buckets.GetTFOptions(), "names_list") 44 | for _, fullBucketName := range names { 45 | // alpha command to list buckets has --json instead of format=json 46 | gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectID, "--json"}) 47 | op := gcloud.Run(t, fmt.Sprintf("alpha storage ls --buckets gs://%s", fullBucketName), gcloudArgs).Array()[0] 48 | 49 | // verify lifecycle rules 50 | lifecycle := op.Get("metadata.lifecycle.rule").Array()[0] 51 | assert.Equal("NEARLINE", lifecycle.Get("action.storageClass").String(), "lifecycle action sets NEARLINE storageClass") 52 | assert.Equal("SetStorageClass", lifecycle.Get("action.type").String(), "lifecycle action is SetStorageClass") 53 | assert.Equal("10", lifecycle.Get("condition.age").String(), "lifecycle condition is age 10") 54 | assert.ElementsMatch([]string{"MULTI_REGIONAL", "STANDARD", "DURABLE_REDUCED_AVAILABILITY"}, utils.GetResultStrSlice(lifecycle.Get("condition.matchesStorageClass").Array()), "lifecycle conditions match") 55 | 56 | // peel bucket name from prefix and randomized suffix 57 | parts := strings.Split(fullBucketName, "-") 58 | bucketName := parts[len(parts) - 2] 59 | 60 | switch bucketName { 61 | case "one": 62 | // bucket with suffix one 63 | assert.True(op.Get("metadata.iamConfiguration.bucketPolicyOnly.enabled").Bool(), "bucketPolicyOnly is enabled") 64 | assert.True(op.Get("metadata.defaultEventBasedHold").Bool(), "defaultEventBasedHold is enabled") 65 | bucket_lifecycle := op.Get("metadata.lifecycle.rule").Array()[1] 66 | assert.Equal("Delete", bucket_lifecycle.Get("action.type").String(), "bucket lifecycle action is Delete") 67 | assert.Equal("90", bucket_lifecycle.Get("condition.age").String(), "bucket lifecycle condition is age 90") 68 | case "two": 69 | // bucket with suffix two 70 | assert.False(op.Get("metadata.iamConfiguration.bucketPolicyOnly.enabled").Bool(), "bucketPolicyOnly is disabled") 71 | assert.False(op.Get("metadata.defaultEventBasedHold").Bool(), "defaultEventBasedHold is disabled") 72 | gcloud.Run(t, fmt.Sprintf("alpha storage ls --buckets gs://%s/dev/", fullBucketName), gcloudArgs) 73 | gcloud.Run(t, fmt.Sprintf("alpha storage ls --buckets gs://%s/prod/", fullBucketName), gcloudArgs) 74 | bucket_lifecycles := op.Get("metadata.lifecycle.rule").Array() 75 | assert.Equal(1, len(bucket_lifecycles), "Bucket 'two' has 1 lifecycle rule") 76 | assert.Equal("1", op.Get("metadata.retentionPolicy.retentionPeriod").String(), "bucket retention policy retention period is 1") 77 | default: 78 | // fail test if unknown suffix 79 | t.Fatalf("Only expected two buckets with suffixes one and two. Found: %s", fullBucketName) 80 | } 81 | } 82 | }) 83 | buckets.Test() 84 | } 85 | -------------------------------------------------------------------------------- /test/setup/.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfvars 2 | source.sh 3 | -------------------------------------------------------------------------------- /test/setup/iam.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | int_required_roles = [ 19 | "roles/cloudkms.cryptoKeyEncrypterDecrypter", 20 | "roles/iam.serviceAccountUser", 21 | "roles/storage.admin", 22 | ] 23 | } 24 | 25 | resource "google_service_account" "int_test" { 26 | project = module.project.project_id 27 | account_id = "ci-cloud-storage" 28 | display_name = "ci-cloud-storage" 29 | } 30 | 31 | resource "google_project_iam_member" "int_test" { 32 | count = length(local.int_required_roles) 33 | 34 | project = module.project.project_id 35 | role = local.int_required_roles[count.index] 36 | member = "serviceAccount:${google_service_account.int_test.email}" 37 | } 38 | 39 | resource "google_service_account_key" "int_test" { 40 | service_account_id = google_service_account.int_test.id 41 | } 42 | -------------------------------------------------------------------------------- /test/setup/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module "project" { 18 | source = "terraform-google-modules/project-factory/google" 19 | version = "~> 18.0" 20 | 21 | name = "ci-cloud-storage" 22 | random_project_id = "true" 23 | org_id = var.org_id 24 | folder_id = var.folder_id 25 | billing_account = var.billing_account 26 | 27 | activate_apis = [ 28 | "cloudkms.googleapis.com", 29 | "cloudresourcemanager.googleapis.com", 30 | "compute.googleapis.com", 31 | "iam.googleapis.com", 32 | "serviceusage.googleapis.com", 33 | "storage-api.googleapis.com", 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /test/setup/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | value = module.project.project_id 19 | } 20 | 21 | output "sa_key" { 22 | value = google_service_account_key.int_test.private_key 23 | sensitive = true 24 | } 25 | -------------------------------------------------------------------------------- /test/setup/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | variable "org_id" { 17 | description = "The numeric organization id" 18 | } 19 | 20 | variable "folder_id" { 21 | description = "The folder to deploy in" 22 | } 23 | 24 | variable "billing_account" { 25 | description = "The billing account id associated with the project, e.g. XXXXXX-YYYYYY-ZZZZZZ" 26 | } 27 | -------------------------------------------------------------------------------- /test/setup/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 0.13" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | description = "Bucket project id." 19 | type = string 20 | } 21 | 22 | variable "prefix" { 23 | description = "Prefix used to generate the bucket name." 24 | type = string 25 | default = "" 26 | } 27 | 28 | variable "names" { 29 | description = "Bucket name suffixes." 30 | type = list(string) 31 | } 32 | 33 | variable "randomize_suffix" { 34 | description = "Adds an identical, but randomized 4-character suffix to all bucket names" 35 | type = bool 36 | default = false 37 | } 38 | 39 | variable "location" { 40 | description = "Bucket location." 41 | type = string 42 | default = "EU" 43 | } 44 | 45 | variable "storage_class" { 46 | description = "Bucket storage class." 47 | type = string 48 | default = "STANDARD" 49 | } 50 | 51 | variable "force_destroy" { 52 | description = "Optional map of lowercase unprefixed name => boolean, defaults to false." 53 | type = map(bool) 54 | default = {} 55 | } 56 | 57 | variable "versioning" { 58 | description = "Optional map of lowercase unprefixed name => boolean, defaults to false." 59 | type = map(bool) 60 | default = {} 61 | } 62 | 63 | variable "autoclass" { 64 | description = "Optional map of lowercase unprefixed bucket name => boolean, defaults to false." 65 | type = map(bool) 66 | default = {} 67 | } 68 | 69 | variable "hierarchical_namespace" { 70 | description = "Optional map of lowercase unprefixed bucket name => boolean, defaults to false." 71 | type = map(bool) 72 | default = {} 73 | } 74 | 75 | variable "encryption_key_names" { 76 | description = "Optional map of lowercase unprefixed name => string, empty strings are ignored." 77 | type = map(string) 78 | default = {} 79 | } 80 | 81 | variable "bucket_policy_only" { 82 | description = "Disable ad-hoc ACLs on specified buckets. Defaults to true. Map of lowercase unprefixed name => boolean" 83 | type = map(bool) 84 | default = {} 85 | } 86 | 87 | variable "default_event_based_hold" { 88 | description = "Enable event based hold to new objects added to specific bucket. Defaults to false. Map of lowercase unprefixed name => boolean" 89 | type = map(bool) 90 | default = {} 91 | } 92 | 93 | variable "admins" { 94 | description = "IAM-style members who will be granted roles/storage.objectAdmin on all buckets." 95 | type = list(string) 96 | default = [] 97 | } 98 | 99 | variable "creators" { 100 | description = "IAM-style members who will be granted roles/storage.objectCreators on all buckets." 101 | type = list(string) 102 | default = [] 103 | } 104 | 105 | variable "viewers" { 106 | description = "IAM-style members who will be granted roles/storage.objectViewer on all buckets." 107 | type = list(string) 108 | default = [] 109 | } 110 | 111 | variable "hmac_key_admins" { 112 | description = "IAM-style members who will be granted roles/storage.hmacKeyAdmin on all buckets." 113 | type = list(string) 114 | default = [] 115 | } 116 | 117 | variable "storage_admins" { 118 | description = "IAM-style members who will be granted roles/storage.admin on all buckets." 119 | type = list(string) 120 | default = [] 121 | } 122 | 123 | variable "bucket_admins" { 124 | description = "Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket admins." 125 | type = map(string) 126 | default = {} 127 | } 128 | 129 | variable "bucket_creators" { 130 | description = "Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket creators." 131 | type = map(string) 132 | default = {} 133 | } 134 | 135 | variable "bucket_viewers" { 136 | description = "Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket viewers." 137 | type = map(string) 138 | default = {} 139 | } 140 | 141 | variable "bucket_hmac_key_admins" { 142 | description = "Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket HMAC Key admins." 143 | type = map(string) 144 | default = {} 145 | } 146 | 147 | variable "bucket_storage_admins" { 148 | description = "Map of lowercase unprefixed name => comma-delimited IAM-style per-bucket storage admins." 149 | type = map(string) 150 | default = {} 151 | } 152 | 153 | variable "labels" { 154 | description = "Labels to be attached to the buckets" 155 | type = map(string) 156 | default = {} 157 | } 158 | 159 | variable "folders" { 160 | description = "Map of lowercase unprefixed name => list of top level folder objects." 161 | type = map(list(string)) 162 | default = {} 163 | } 164 | 165 | # we need flags to allow member lists to contain dynamic elements 166 | 167 | variable "set_admin_roles" { 168 | description = "Grant roles/storage.objectAdmin role to admins and bucket_admins." 169 | type = bool 170 | default = false 171 | } 172 | 173 | variable "set_creator_roles" { 174 | description = "Grant roles/storage.objectCreator role to creators and bucket_creators." 175 | type = bool 176 | default = false 177 | } 178 | 179 | variable "set_viewer_roles" { 180 | description = "Grant roles/storage.objectViewer role to viewers and bucket_viewers." 181 | type = bool 182 | default = false 183 | } 184 | 185 | variable "set_hmac_key_admin_roles" { 186 | description = "Grant roles/storage.hmacKeyAdmin role to hmac_key_admins and bucket_hmac_key_admins." 187 | type = bool 188 | default = false 189 | } 190 | 191 | variable "set_storage_admin_roles" { 192 | description = "Grant roles/storage.admin role to storage_admins and bucket_storage_admins." 193 | type = bool 194 | default = false 195 | } 196 | 197 | variable "lifecycle_rules" { 198 | type = set(object({ 199 | # Object with keys: 200 | # - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass. 201 | # - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule. 202 | action = object({ 203 | type = string 204 | storage_class = optional(string) 205 | }) 206 | 207 | # Object with keys: 208 | # - age - (Optional) Minimum age of an object in days to satisfy this condition. 209 | # - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field. 210 | # - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition. 211 | # - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY". 212 | # - matches_storage_class - (Optional) Comma delimited string for storage class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY. 213 | # - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition. 214 | # - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition. 215 | # - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition. 216 | # - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition. 217 | # - days_since_custom_time - (Optional) The number of days from the Custom-Time metadata attribute after which this condition becomes true. 218 | # - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object. 219 | # - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent. 220 | condition = object({ 221 | age = optional(number) 222 | send_age_if_zero = optional(bool) 223 | created_before = optional(string) 224 | with_state = optional(string) 225 | matches_storage_class = optional(string) 226 | matches_prefix = optional(string) 227 | matches_suffix = optional(string) 228 | num_newer_versions = optional(number) 229 | custom_time_before = optional(string) 230 | days_since_custom_time = optional(number) 231 | days_since_noncurrent_time = optional(number) 232 | noncurrent_time_before = optional(string) 233 | }) 234 | })) 235 | description = "List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches_storage_class should be a comma delimited string." 236 | default = [] 237 | } 238 | 239 | variable "bucket_lifecycle_rules" { 240 | type = map(set(object({ 241 | # Object with keys: 242 | # - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass. 243 | # - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule. 244 | action = object({ 245 | type = string 246 | storage_class = optional(string) 247 | }) 248 | 249 | # Object with keys: 250 | # - age - (Optional) Minimum age of an object in days to satisfy this condition. 251 | # - send_age_if_zero - (Optional) While set true, num_newer_versions value will be sent in the request even for zero value of the field. 252 | # - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition. 253 | # - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY". 254 | # - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY. 255 | # - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition. 256 | # - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition 257 | # - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition. 258 | # - custom_time_before - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when the customTime metadata for the object is set to an earlier date than the date used in this lifecycle condition. 259 | # - days_since_custom_time - (Optional) Days since the date set in the customTime metadata for the object. 260 | # - days_since_noncurrent_time - (Optional) Relevant only for versioned objects. Number of days elapsed since the noncurrent timestamp of an object. 261 | # - noncurrent_time_before - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. 2017-06-13) when the object became nonconcurrent. 262 | condition = object({ 263 | age = optional(number) 264 | send_age_if_zero = optional(bool) 265 | created_before = optional(string) 266 | with_state = optional(string) 267 | matches_storage_class = optional(string) 268 | matches_prefix = optional(string) 269 | matches_suffix = optional(string) 270 | num_newer_versions = optional(number) 271 | custom_time_before = optional(string) 272 | days_since_custom_time = optional(number) 273 | days_since_noncurrent_time = optional(number) 274 | noncurrent_time_before = optional(string) 275 | }) 276 | }))) 277 | description = "Additional lifecycle_rules for specific buckets. Map of lowercase unprefixed name => list of lifecycle rules to configure." 278 | default = {} 279 | } 280 | 281 | variable "cors" { 282 | description = "Set of maps of mixed type attributes for CORS values. See appropriate attribute types here: https://www.terraform.io/docs/providers/google/r/storage_bucket.html#cors" 283 | type = list(object({ 284 | origin = optional(list(string)) 285 | method = optional(list(string)) 286 | response_header = optional(list(string)) 287 | max_age_seconds = optional(number) 288 | })) 289 | default = [] 290 | } 291 | 292 | variable "website" { 293 | type = object({ 294 | main_page_suffix = optional(string) 295 | not_found_page = optional(string) 296 | }) 297 | default = {} 298 | description = "Map of website values. Supported attributes: main_page_suffix, not_found_page" 299 | } 300 | 301 | variable "retention_policy" { 302 | type = any 303 | default = {} 304 | description = "Map of retention policy values. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket#retention_policy" 305 | } 306 | 307 | variable "custom_placement_config" { 308 | type = any 309 | default = {} 310 | description = "Map of lowercase unprefixed name => custom placement config object. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket#custom_placement_config" 311 | } 312 | 313 | variable "logging" { 314 | description = "Map of lowercase unprefixed name => bucket logging config object. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#logging" 315 | type = any 316 | default = {} 317 | } 318 | 319 | variable "set_hmac_access" { 320 | description = "Set S3 compatible access to GCS." 321 | type = bool 322 | default = false 323 | } 324 | 325 | variable "hmac_service_accounts" { 326 | description = "List of HMAC service accounts to grant access to GCS." 327 | type = map(string) 328 | default = {} 329 | } 330 | 331 | variable "public_access_prevention" { 332 | description = "Prevents public access to a bucket. Acceptable values are inherited or enforced. If inherited, the bucket uses public access prevention, only if the bucket is subject to the public access prevention organization policy constraint." 333 | type = string 334 | default = "inherited" 335 | } 336 | 337 | variable "soft_delete_policy" { 338 | description = "Soft delete policies to apply. Map of lowercase unprefixed name => soft delete policy. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#nested_soft_delete_policy" 339 | type = map(any) 340 | default = {} 341 | } 342 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | 21 | google = { 22 | source = "hashicorp/google" 23 | version = ">= 6.9.0, < 7" 24 | } 25 | 26 | random = { 27 | source = "hashicorp/random" 28 | version = ">= 2.1" 29 | } 30 | } 31 | 32 | provider_meta "google" { 33 | module_name = "blueprints/terraform/terraform-google-cloud-storage/v11.0.0" 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------