├── .github ├── conventional-commit-lint.yaml ├── release-please.yml ├── renovate.json ├── trusted-contribution.yml └── workflows │ ├── lint.yaml │ └── stale.yml ├── .gitignore ├── .terraform.lock ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── build ├── int.cloudbuild.yaml └── lint.cloudbuild.yaml ├── docs └── upgrading_to_v5.0.md ├── examples ├── bastion_group │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── iap_tunneling │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── simple_example │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf └── two_service_example │ ├── README.md │ ├── iam.tf │ ├── instances.tf │ ├── main.tf │ ├── test.yaml │ └── variables.tf ├── main.tf ├── metadata.yaml ├── modules ├── bastion-group │ ├── README.md │ ├── main.tf │ ├── metadata.yaml │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── iap-tunneling │ ├── README.md │ ├── main.tf │ ├── metadata.yaml │ ├── variables.tf │ └── versions.tf ├── outputs.tf ├── test ├── integration │ ├── bastion_group │ │ └── bastion_group_test.go │ ├── discover_test.go │ ├── go.mod │ ├── go.sum │ ├── iap_tunneling │ │ └── iap_tunneling_test.go │ └── simple_example │ │ └── simple_example_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 -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} module-swapper 48 | - run: docker run --rm -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} /usr/local/bin/test_lint.sh 49 | -------------------------------------------------------------------------------- /.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 | # OSX trash 5 | .DS_Store 6 | 7 | # Python 8 | *.pyc 9 | 10 | # Emacs save files 11 | *~ 12 | \#*\# 13 | .\#* 14 | 15 | # Vim-related files 16 | [._]*.s[a-w][a-z] 17 | [._]s[a-w][a-z] 18 | *.un~ 19 | Session.vim 20 | .netrwhist 21 | 22 | ### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore 23 | 24 | # Local .terraform directories 25 | **/.terraform/* 26 | 27 | # .tfstate files 28 | *.tfstate 29 | *.tfstate.* 30 | # Terraform lock files 31 | **/.terraform.lock.hcl 32 | # Crash log files 33 | crash.log 34 | 35 | # Kitchen files 36 | **/inspec.lock 37 | **/.kitchen 38 | **/kitchen.local.yml 39 | **/Gemfile.lock 40 | 41 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 42 | # .tfvars files are managed as part of configuration and so should be included in 43 | # version control. 44 | **/*.tfvars 45 | 46 | credentials.json 47 | 48 | # tf lock file 49 | .terraform.lock.hcl 50 | -------------------------------------------------------------------------------- /.terraform.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terraform-google-modules/terraform-google-bastion-host/0ec29c1c0087e586e94f36b8d47add8821ef95ed/.terraform.lock -------------------------------------------------------------------------------- /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 | ## [8.0.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v7.1.0...v8.0.0) (2024-10-29) 11 | 12 | 13 | ### ⚠ BREAKING CHANGES 14 | 15 | * **deps:** Update Terraform terraform-google-modules/vm/google to v12 ([#212](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/212)) 16 | 17 | ### Features 18 | 19 | * **bastion-group:** add variable for additional_ports ([#215](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/215)) ([4bbafb0](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/4bbafb0f14f2fc716cadf94ef4b4658b95f948e4)) 20 | * implement firewall priority in iap-tunneling module ([#216](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/216)) ([4c84d22](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/4c84d2285a2e2f31a0044ac3a3bdbea38b7003e2)) 21 | 22 | 23 | ### Bug Fixes 24 | 25 | * **deps:** Update Terraform terraform-google-modules/vm/google to v12 ([#212](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/212)) ([1eb600a](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/1eb600aa7050fff86a7bec4d87513c8e9ca269b8)) 26 | 27 | ## [7.1.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v7.0.0...v7.1.0) (2024-09-06) 28 | 29 | 30 | ### Features 31 | 32 | * **deps:** Update Terraform Google Provider to v6 (major) ([#205](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/205)) ([bfef016](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/bfef016667783409546ae1feaad4df01174ddb61)) 33 | 34 | 35 | ### Bug Fixes 36 | 37 | * correct access_config to block ([#209](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/209)) ([1413f7e](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/1413f7ea46f38e15956a0ae3054ee554ef70c5df)) 38 | * set empty access_config to null ([#206](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/206)) ([c0b5acf](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/c0b5acf3ca51a4917010f0095621d6743f2b4689)) 39 | 40 | ## [7.0.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v6.0.0...v7.0.0) (2024-08-21) 41 | 42 | 43 | ### ⚠ BREAKING CHANGES 44 | 45 | * **deps:** Update Terraform terraform-google-modules/vm/google to v11 ([#186](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/186)) 46 | 47 | ### Features 48 | 49 | * support can_ip_forward ([#184](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/184)) ([a7705b0](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/a7705b015e8138b4b57a526f772ac3e5d06c8c32)) 50 | * Support setting a static ip for the bastion ([#197](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/197)) ([b09be98](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/b09be9886946768c785b156c11081aed07f2a147)) 51 | 52 | 53 | ### Bug Fixes 54 | 55 | * **deps:** Update Terraform terraform-google-modules/vm/google to v11 ([#186](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/186)) ([0c7a342](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/0c7a34278fab3223c3965092f7614f7cf078f62c)) 56 | * Update Debian Image to 12 ([#179](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/179)) ([ae88275](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/ae88275381a451ee5d0cc94067526b5684d78780)) 57 | 58 | ## [6.0.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v5.3.0...v6.0.0) (2023-10-30) 59 | 60 | 61 | ### ⚠ BREAKING CHANGES 62 | 63 | * **deps:** Update Terraform terraform-google-modules/vm/google to v10 ([#153](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/153)) 64 | 65 | ### Bug Fixes 66 | 67 | * **deps:** Update Terraform terraform-google-modules/vm/google to v10 ([#153](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/153)) ([b2333ee](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/b2333ee6e1e0551b022257bbe019767bb5088a3f)) 68 | * upgraded versions.tf to include minor bumps from tpg v5 ([#157](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/157)) ([4456230](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/4456230664f86b80a2db2f98eef720abc793fd80)) 69 | 70 | ## [5.3.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v5.2.0...v5.3.0) (2023-04-06) 71 | 72 | 73 | ### Features 74 | 75 | * add disk labels to bastion vm ([#128](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/128)) ([b1edf32](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/b1edf3268f458cbe1c02da8b0ea75a9db9381b59)) 76 | 77 | ## [5.2.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v5.1.1...v5.2.0) (2023-01-25) 78 | 79 | 80 | ### Features 81 | 82 | * adds `region` setting used to configure the instance template ([#131](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/131)) ([00a863c](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/00a863ce0f37d69e6a9ac256aa358114a3a38bec)) 83 | 84 | ## [5.1.1](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v5.1.0...v5.1.1) (2023-01-20) 85 | 86 | 87 | ### Bug Fixes 88 | 89 | * fixes lint issues and generates metadata ([#126](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/126)) ([b6267e6](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/b6267e6b69d0fe2ecdb53905912cd8619fb2e04d)) 90 | 91 | ## [5.1.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v5.0.1...v5.1.0) (2022-10-29) 92 | 93 | 94 | ### Features 95 | 96 | * apply labels to bastion instance ([#114](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/114)) ([5dab8d1](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/5dab8d17b447fdecc0d164b2b48d1ba881b44a89)) 97 | * Optionally pass additional networks to the instance template ([#117](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/117)) ([5c601c9](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/5c601c9406a8d9066755f7fa5c4b84f934817bef)) 98 | 99 | 100 | ### Bug Fixes 101 | 102 | * **deps:** update module github.com/stretchr/testify to v1.8.1 ([#120](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/120)) ([6140420](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/6140420450097c6f5875379d2dd8ae936b2fd270)) 103 | 104 | ## [5.0.1](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v5.0.0...v5.0.1) (2022-09-07) 105 | 106 | 107 | ### Bug Fixes 108 | 109 | * try() to fix index errors ([#108](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/108)) ([f566e8d](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/f566e8d9ebfd720f1832e5434ead017ea81849d1)) 110 | 111 | ## [5.0.0](https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v4.1.0...v5.0.0) (2022-03-31) 112 | 113 | 114 | ### ⚠ BREAKING CHANGES 115 | 116 | * renamed the ephemeral_ip variable to external_ip (#105) 117 | * Update bastion image family to debian-11 (#102) 118 | 119 | ### Features 120 | 121 | * Update bastion image family to debian-11 ([#102](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/102)) ([9f935eb](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/9f935eb1cc999a2c18eae148516ebd43e110cc79)) 122 | 123 | 124 | ### Bug Fixes 125 | 126 | * renamed the ephemeral_ip variable to external_ip ([#105](https://github.com/terraform-google-modules/terraform-google-bastion-host/issues/105)) ([1a63d4c](https://github.com/terraform-google-modules/terraform-google-bastion-host/commit/1a63d4ca0470ba423abb2aabe218f6c79f7c7fac)) 127 | 128 | ## [4.1.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v4.0.0...v4.1.0) (2021-11-25) 129 | 130 | 131 | ### Features 132 | 133 | * update TPG version constraints to allow 4.0 ([#98](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/98)) ([83f57db](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/83f57db571f66b457cee710276627b041a1374b5)) 134 | 135 | ## [4.0.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v3.2.0...v4.0.0) (2021-09-10) 136 | 137 | ### ⚠ BREAKING CHANGES 138 | 139 | * Update default image family and image project ([#89](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/89)) ([090c0ea](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/090c0ea0254cbd31434fc974f6219e2c3c3b8d86)) 140 | 141 | ### Bug Fixes 142 | 143 | * Update default image family and image project to fix [#88](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/88) ([#89](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/89)) ([090c0ea](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/090c0ea0254cbd31434fc974f6219e2c3c3b8d86)) 144 | 145 | 146 | ### Miscellaneous Chores 147 | 148 | * release 4.0.0 ([f5de94c](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/f5de94ce74c8aff7e88ec9cefd0effa956e02bc3)) 149 | 150 | ## [3.2.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v3.1.0...v3.2.0) (2021-04-09) 151 | 152 | 153 | ### Features 154 | 155 | * Add option for creating firewall rule. ([#82](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/82)) ([cdd37ff](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/cdd37ff566eebb3879336944bdf009e26d3fd2ff)) 156 | * add preemptible option. ([#83](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/83)) ([7303a05](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/7303a054e5c0368cdd4e66764ed4f672dbbba832)) 157 | 158 | ## [3.1.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v3.0.0...v3.1.0) (2021-02-23) 159 | 160 | 161 | ### Features 162 | 163 | * Add ephemeral_ip to bastion host. ([#73](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/73)) ([c4dbeab](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/c4dbeab0ab89ef52565020821e6fd24a9c18078a)) 164 | 165 | ## [3.0.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.10.2...v3.0.0) (2021-01-13) 166 | 167 | 168 | ### ⚠ BREAKING CHANGES 169 | 170 | * Bump instance template version to support terraform 0.14 (#70) 171 | 172 | ### Features 173 | 174 | * Bump instance template version to support terraform 0.14 ([#70](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/70)) ([be00982](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/be0098210d789f6e2a11de347dd244380f151114)) 175 | 176 | ### [2.10.2](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.10.1...v2.10.2) (2020-12-15) 177 | 178 | 179 | ### Bug Fixes 180 | 181 | * Pass host_project variable into instance_template module ([#63](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/63)) ([1c88a0c](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/1c88a0ccd58a5221e2203b2c2a21953dbdef6579)) 182 | * pass labels into instance template ([#69](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/69)) ([c4ff7e7](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/c4ff7e72c36c506a4aa4011407653dcceb47bcc2)) 183 | 184 | ### [2.10.1](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.10.0...v2.10.1) (2020-12-10) 185 | 186 | 187 | ### Bug Fixes 188 | 189 | * Remove < 0.14 constraint [bot-pr] ([#64](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/64)) ([6690be3](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/6690be327c335522fb5db12b67ff90b5b1c8ad51)) 190 | 191 | ## [2.10.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.9.0...v2.10.0) (2020-10-07) 192 | 193 | 194 | ### Features 195 | 196 | * support additional metadata for instances ([#52](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/52)) ([46456a2](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/46456a29405f207b211481846d4d613f3e7430ac)) 197 | 198 | ## [2.9.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.8.0...v2.9.0) (2020-10-01) 199 | 200 | 201 | ### Features 202 | 203 | * Support terraform 0.13 ([#55](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/55)) ([0739dfb](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/0739dfb7fe0e07ea1a8b409edbcf02efa873d2a5)) 204 | 205 | ## [2.8.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.7.0...v2.8.0) (2020-09-22) 206 | 207 | 208 | ### Features 209 | 210 | * Fix failing tests in master ([#53](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/53)) ([79f0249](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/79f02493f1c619113f757a6fcdecb9d54cd1ea8c)) 211 | 212 | ## [2.7.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.6.0...v2.7.0) (2020-06-24) 213 | 214 | 215 | ### Features 216 | 217 | * Added option to specify the fw rule name for ssh to health checks ([#45](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/45)) ([4ef9f78](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/4ef9f78297deeaf00c8d296be55e39220d5cb551)) 218 | 219 | ## [2.6.0](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/compare/v2.5.0...v2.6.0) (2020-06-11) 220 | 221 | 222 | ### Features 223 | 224 | * update instance template version (see: [#40](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/issues/40)) ([6dc6299](https://www.github.com/terraform-google-modules/terraform-google-bastion-host/commit/6dc62991daa04918e335e096f5ee4ad3a42ceff2)) 225 | 226 | ## [2.5.0] - 2020-05-11 227 | - Disk size and type variable override [#39] 228 | 229 | ## [2.4.0] - 2020-05-06 230 | - Service Account variable override [#38] 231 | 232 | ## [2.3.0] - 2020-04-29 233 | - Added image variable [#37] 234 | 235 | ## [2.2.0] - 2020-04-03 236 | 237 | - Add name_prefix variable for instance template [#35] 238 | - Bump Google provider version to 3.15 239 | - Remove google-beta provider since it's no longer needed 240 | 241 | 242 | ## [2.1.1] - 2020-03-11 243 | - Added type annotations to variables [#34] 244 | 245 | ## [2.1.0] - 2020-01-22 246 | - Bumped Google provider to 3.4 247 | - Pulled IAP Tunnelling into separate module [#29] 248 | 249 | ## [2.0.0] - 2020-01-10 250 | - Added submodule and example for `bastion-group` [#27] 251 | 252 | ## [1.0.1] - 2020-01-03 253 | 254 | - Fixed deprecation warnings due to quotes 255 | - Added more integration tests 256 | 257 | ## [1.0.0] - 2019-11-22 258 | 259 | ### Fixed 260 | - **Breaking**: Fixed issue with recreating custom roles by appending a random ID. Existing users can set `random_role_id` to `false` to avoid recreating the custom role. [#16] 261 | 262 | ## [0.2.0] - 2019-11-11 263 | 264 | ### Added 265 | - Add support for img family, img project, shielded_vm. [#10] 266 | - Added support for setting Shared VPC firewall rules. [#6](https://github.com/terraform-google-modules/terraform-google-bastion-host/pull/6) 267 | 268 | ### Fixed 269 | - Fixed issue with using `scopes` variable. [#7](https://github.com/terraform-google-modules/terraform-google-bastion-host/pull/7) 270 | 271 | ## [0.1.0] - 2019-08-02 272 | 273 | - Initial release 274 | 275 | [Unreleased]: https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v1.0.0...HEAD 276 | [1.0.0]: https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v0.2.0...v1.0.0 277 | [0.2.0]: https://github.com/terraform-google-modules/terraform-google-bastion-host/compare/v0.1.0...v0.2.0 278 | [0.1.0]: https://github.com/terraform-google-modules/terraform-google-bastion-host/releases/tag/v0.1.0 279 | 280 | [#16]: https://github.com/terraform-google-modules/terraform-google-bastion-host/pull/16 281 | [#10]: https://github.com/terraform-google-modules/terraform-google-bastion-host/pull/10 282 | -------------------------------------------------------------------------------- /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 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 | ## Generating Documentation for Inputs and Outputs 6 | 7 | The Inputs and Outputs tables in the READMEs of the root module, 8 | submodules, and example modules are automatically generated based on 9 | the `variables` and `outputs` of the respective modules. These tables 10 | must be refreshed if the module interfaces are changed. 11 | 12 | ### Dependencies 13 | 14 | The following dependencies must be installed on the development system: 15 | 16 | - [make] 17 | - [terraform-docs] v0.6.0 18 | 19 | ### Execution 20 | 21 | Run `make generate_docs` to generate new Inputs and Outputs tables. 22 | 23 | ## Integration Testing 24 | 25 | Integration tests are used to verify the behaviour of the root module, 26 | submodules, and example modules. Additions, changes, and fixes should 27 | be accompanied with tests. 28 | 29 | The integration tests are run using [Kitchen][kitchen], 30 | [Kitchen-Terraform][kitchen-terraform], and [InSpec][inspec]. These 31 | tools are packaged within a Docker image for convenience. 32 | 33 | The general strategy for these tests is to verify the behaviour of the 34 | [example modules](./examples), thus ensuring that the root module, 35 | submodules, and example modules are all functionally correct. 36 | 37 | ### Dependencies 38 | 39 | The following dependencies must be installed on the development system: 40 | 41 | - [Docker Engine][docker-engine] 42 | - [Google Cloud SDK][google-cloud-sdk] 43 | - [make] 44 | 45 | ### Inputs 46 | 47 | Test instances are defined in the 48 | [Kitchen configuration file](./kitchen.yml). The inputs of each Kitchen 49 | instance may be configured with the `driver.variables` key in a 50 | local Kitchen configuration file located at `./kitchen.local.yml` or in 51 | a Terraform variables file located at 52 | `./test/fixtures//variables.tfvars`. 53 | 54 | ### Credentials 55 | 56 | Download the key of a Service Account with the 57 | [required roles][required-roles] to `./credentials.json`. 58 | 59 | ### Interactive Execution 60 | 61 | 1. Run `make docker_run` to start the testing Docker container in 62 | interactive mode. 63 | 64 | 1. Run `kitchen create ` to initialize the working 65 | directory for an example module. 66 | 67 | 1. Run `kitchen converge ` to apply the example module. 68 | 69 | 1. Run `kitchen verify ` to test the example module. 70 | 71 | 1. Run `kitchen destroy ` to destroy the example module 72 | state. 73 | 74 | ### Noninteractive Execution 75 | 76 | Run `make test_integration_docker` to test all of the example modules 77 | noninteractively. 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 | ### Dependencies 85 | 86 | The following dependencies must be installed on the development system: 87 | 88 | - [flake8] 89 | - [gofmt] 90 | - [hadolint] 91 | - [make] 92 | - [shellcheck] 93 | - [Terraform][terraform] v0.11 94 | 95 | ### Execution 96 | 97 | Run `make check`. 98 | 99 | [docker-engine]: https://www.docker.com/products/docker-engine 100 | [flake8]: http://flake8.pycqa.org/en/latest/ 101 | [gofmt]: https://golang.org/cmd/gofmt/ 102 | [google-cloud-sdk]: https://cloud.google.com/sdk/install 103 | [hadolint]: https://github.com/hadolint/hadolint 104 | [inspec]: https://inspec.io/ 105 | [kitchen-terraform]: https://github.com/newcontext-oss/kitchen-terraform 106 | [kitchen]: https://kitchen.ci/ 107 | [make]: https://en.wikipedia.org/wiki/Make_(software) 108 | [shellcheck]: https://www.shellcheck.net/ 109 | [terraform-docs]: https://github.com/segmentio/terraform-docs 110 | [terraform]: https://terraform.io/ 111 | -------------------------------------------------------------------------------- /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 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 | # 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 | # Please note that this file was generated from [terraform-google-module-template](https://github.com/terraform-google-modules/terraform-google-module-template). 16 | # Please make sure to contribute relevant changes upstream! 17 | 18 | # Make will use bash instead of sh 19 | SHELL := /usr/bin/env bash 20 | 21 | DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.22 22 | DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools 23 | REGISTRY_URL := gcr.io/cloud-foundation-cicd 24 | 25 | # Enter docker container for local development 26 | .PHONY: docker_run 27 | docker_run: 28 | docker run --rm -it \ 29 | -e SERVICE_ACCOUNT_JSON \ 30 | -v "$(CURDIR)":/workspace \ 31 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 32 | /bin/bash 33 | 34 | # Execute prepare tests within the docker container 35 | .PHONY: docker_test_prepare 36 | docker_test_prepare: 37 | docker run --rm -it \ 38 | -e SERVICE_ACCOUNT_JSON \ 39 | -e TF_VAR_org_id \ 40 | -e TF_VAR_folder_id \ 41 | -e TF_VAR_billing_account \ 42 | -v "$(CURDIR)":/workspace \ 43 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 44 | /usr/local/bin/execute_with_credentials.sh prepare_environment 45 | 46 | # Clean up test environment within the docker container 47 | .PHONY: docker_test_cleanup 48 | docker_test_cleanup: 49 | docker run --rm -it \ 50 | -e SERVICE_ACCOUNT_JSON \ 51 | -e TF_VAR_org_id \ 52 | -e TF_VAR_folder_id \ 53 | -e TF_VAR_billing_account \ 54 | -v "$(CURDIR)":/workspace \ 55 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 56 | /usr/local/bin/execute_with_credentials.sh cleanup_environment 57 | 58 | # Execute integration tests within the docker container 59 | .PHONY: docker_test_integration 60 | docker_test_integration: 61 | docker run --rm -it \ 62 | -e SERVICE_ACCOUNT_JSON \ 63 | -v "$(CURDIR)":/workspace \ 64 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 65 | /usr/local/bin/test_integration.sh 66 | 67 | # Execute lint tests within the docker container 68 | .PHONY: docker_test_lint 69 | docker_test_lint: 70 | docker run --rm -it \ 71 | -v "$(CURDIR)":/workspace \ 72 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 73 | /usr/local/bin/test_lint.sh 74 | 75 | # Generate documentation 76 | .PHONY: docker_generate_docs 77 | docker_generate_docs: 78 | docker run --rm -it \ 79 | -v "$(CURDIR)":/workspace \ 80 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 81 | /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_docs' 82 | 83 | # Alias for backwards compatibility 84 | .PHONY: generate_docs 85 | generate_docs: docker_generate_docs 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-google-bastion-host 2 | 3 | This module will generate a bastion host vm compatible with [OS Login](https://cloud.google.com/compute/docs/oslogin/) and [IAP Tunneling](https://cloud.google.com/iap/) that can be used to access internal VMs. 4 | 5 | This module will: 6 | 7 | - Create a dedicated service account for the bastion host 8 | - Create a GCE instance to be the bastion host 9 | - Create a firewall rule to allow TCP:22 SSH access from the IAP to the bastion 10 | - Necessary IAM bindings to allow IAP and OS Logins from specified members 11 | 12 | ## Usage 13 | 14 | Basic usage of this module is as follows: 15 | 16 | ```hcl 17 | module "iap_bastion" { 18 | source = "terraform-google-modules/bastion-host/google" 19 | 20 | project = var.project 21 | zone = var.zone 22 | network = google_compute_network.net.self_link 23 | subnet = google_compute_subnetwork.net.self_link 24 | members = [ 25 | "group:devs@example.com", 26 | "user:me@example.com", 27 | ] 28 | } 29 | ``` 30 | 31 | Functional example is included in the 32 | [examples](./examples/) directory. 33 | 34 | ## Requirements 35 | 36 | These sections describe requirements for using this module. 37 | 38 | ### Software 39 | 40 | The following dependencies must be available: 41 | 42 | - [Terraform][terraform] >= v0.12 43 | - [Terraform Provider for GCP][terraform-provider-gcp] 44 | 45 | ### APIs 46 | 47 | A project with the following APIs enabled must be used to host the 48 | resources of this module: 49 | 50 | - Google Cloud Storage JSON API: `storage-api.googleapis.com` 51 | - Compute Engine API: `compute.googleapis.com` 52 | - Cloud Identity-Aware Proxy API: `iap.googleapis.com` 53 | - OS Login API: `oslogin.googleapis.com` 54 | 55 | The [Project Factory module][project-factory-module] can be used to 56 | provision a project with the necessary APIs enabled. 57 | 58 | ### Permissions 59 | 60 | This module only sets up permissions for the bastion service account, not the users who need access. To allow access, grant one of the following instance access roles. 61 | 62 | * `roles/compute.osLogin` Does not grant administrator permissions 63 | * `roles/compute.osAdminLogin` Grants administrator permissions. 64 | 65 | If the user does not share the same domain as the org the bastion is in, you will also need to grant that user `roles/compute.osLoginExternalUser`. This is to prevent external SSH access from being granted at the project level. See the [OS Login documentation](https://cloud.google.com/compute/docs/instances/managing-instance-access#configure_users) for more information. 66 | 67 | 68 | ## Inputs 69 | 70 | | Name | Description | Type | Default | Required | 71 | |------|-------------|------|---------|:--------:| 72 | | access\_config | Access configs for network, nat\_ip and DNS |
list(object({
network_tier = string
nat_ip = string
public_ptr_domain_name = string
}))
|
[
{
"nat_ip": "",
"network_tier": "PREMIUM",
"public_ptr_domain_name": ""
}
]
| no | 73 | | additional\_networks | Additional network interface details for the instance template, if any. |
list(object({
network = string
subnetwork = string
subnetwork_project = string
network_ip = string
nic_type = string
stack_type = string
queue_count = number
access_config = list(object({
nat_ip = string
network_tier = string
}))
ipv6_access_config = list(object({
network_tier = string
}))
alias_ip_range = list(object({
ip_cidr_range = string
subnetwork_range_name = string
}))
}))
| `[]` | no | 74 | | additional\_ports | A list of additional ports/ranges to open access to on the instances from IAP. | `list(string)` | `[]` | no | 75 | | can\_ip\_forward | Whether the bastion should allow IP forwarding. | `bool` | `false` | no | 76 | | create\_firewall\_rule | If we need to create the firewall rule or not. | `bool` | `true` | no | 77 | | create\_instance\_from\_template | Whether to create and instance from the template or not. If false, no instance is created, but the instance template is created and usable by a MIG | `bool` | `true` | no | 78 | | disk\_labels | Key-value map of labels to assign to the bastion host disk | `map(any)` | `{}` | no | 79 | | disk\_size\_gb | Boot disk size in GB | `number` | `100` | no | 80 | | disk\_type | Boot disk type, can be either pd-ssd, local-ssd, or pd-standard | `string` | `"pd-standard"` | no | 81 | | external\_ip | Set to true if an ephemeral or static external IP/DNS is required, must also set access\_config if true | `bool` | `false` | no | 82 | | fw\_name\_allow\_ssh\_from\_iap | Firewall rule name for allowing SSH from IAP | `string` | `"allow-ssh-from-iap-to-tunnel"` | no | 83 | | host\_project | The network host project ID | `string` | `""` | no | 84 | | image | Source image for the Bastion. If image is not specified, image\_family will be used (which is the default). | `string` | `""` | no | 85 | | image\_family | Source image family for the Bastion. | `string` | `"debian-12"` | no | 86 | | image\_project | Project where the source image for the Bastion comes from | `string` | `"debian-cloud"` | no | 87 | | labels | Key-value map of labels to assign to the bastion host | `map(any)` | `{}` | no | 88 | | machine\_type | Instance type for the Bastion host | `string` | `"n1-standard-1"` | no | 89 | | members | List of IAM resources to allow access to the bastion host | `list(string)` | `[]` | no | 90 | | metadata | Key-value map of additional metadata to assign to the instances | `map(string)` | `{}` | no | 91 | | name | Name of the Bastion instance | `string` | `"bastion-vm"` | no | 92 | | name\_prefix | Name prefix for instance template | `string` | `"bastion-instance-template"` | no | 93 | | network | Self link for the network on which the Bastion should live | `string` | n/a | yes | 94 | | network\_ip | Private IP address for the bastion host | `string` | `""` | no | 95 | | preemptible | Allow the instance to be preempted | `bool` | `false` | no | 96 | | project | The project ID to deploy to | `string` | n/a | yes | 97 | | random\_role\_id | Enables role random id generation. | `bool` | `true` | no | 98 | | region | The region where the bastion instance template will live | `string` | `null` | no | 99 | | scopes | List of scopes to attach to the bastion host | `list(string)` |
[
"cloud-platform"
]
| no | 100 | | service\_account\_email | If set, the service account and its permissions will not be created. The service account being passed in should have at least the roles listed in the `service_account_roles` variable so that logging and OS Login work as expected. | `string` | `""` | no | 101 | | service\_account\_name | Account ID for the service account | `string` | `"bastion"` | no | 102 | | service\_account\_roles | List of IAM roles to assign to the service account. | `list(string)` |
[
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
"roles/monitoring.viewer",
"roles/compute.osLogin"
]
| no | 103 | | service\_account\_roles\_supplemental | An additional list of roles to assign to the bastion if desired | `list(string)` | `[]` | no | 104 | | shielded\_vm | Enable shielded VM on the bastion host (recommended) | `bool` | `true` | no | 105 | | startup\_script | Render a startup script with a template. | `string` | `""` | no | 106 | | subnet | Self link for the subnet on which the Bastion should live. Can be private when using IAP | `string` | n/a | yes | 107 | | tags | Network tags, provided as a list | `list(string)` | `[]` | no | 108 | | zone | The primary zone where the bastion host will live | `string` | `"us-central1-a"` | no | 109 | 110 | ## Outputs 111 | 112 | | Name | Description | 113 | |------|-------------| 114 | | hostname | Host name of the bastion | 115 | | instance\_template | Self link of the bastion instance template for use with a MIG | 116 | | ip\_address | Internal IP address of the bastion host | 117 | | self\_link | Self link of the bastion host | 118 | | service\_account | The email for the service account created for the bastion host | 119 | 120 | 121 | 122 | ## Contributing 123 | 124 | Refer to the [contribution guidelines](./CONTRIBUTING.md) for 125 | information on contributing to this module. 126 | 127 | [iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google 128 | [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google 129 | [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html 130 | [terraform]: https://www.terraform.io/downloads.html 131 | -------------------------------------------------------------------------------- /build/int.cloudbuild.yaml: -------------------------------------------------------------------------------- 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 | # 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: create 28 | name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' 29 | args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose'] 30 | - id: converge 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 apply --verbose'] 33 | - id: verify 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 verify --verbose'] 36 | - id: destroy 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 teardown --verbose'] 39 | tags: 40 | - 'ci' 41 | - 'integration' 42 | substitutions: 43 | _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' 44 | _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.22' 45 | -------------------------------------------------------------------------------- /build/lint.cloudbuild.yaml: -------------------------------------------------------------------------------- 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 | # 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.22' 25 | -------------------------------------------------------------------------------- /docs/upgrading_to_v5.0.md: -------------------------------------------------------------------------------- 1 | # Upgrading to terraform-google-bastion-host v5.x 2 | 3 | The v5.0 release of Google Bastion Host is a backwards incompatible release. 4 | Below a list of the breaking changes and the migration instructions. 5 | 6 | ## ⚠ BREAKING CHANGES 7 | 8 | * Renamed the `ephemeral_ip` variable to `external_ip` as it is possible to specify not only an ephemeral IP but also a static external IP. 9 | 10 | ## Migration Instructions 11 | 12 | The following diff shows the breaking changes introduced in version 5 compared to version 4. 13 | 14 | ```diff 15 | module "iap_bastion" { 16 | source = "terraform-google-modules/bastion-host/google" 17 | - version = "v4.1" 18 | + version = "v5.0" 19 | 20 | - ephemeral_ip = true 21 | + external_ip = true 22 | 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /examples/bastion_group/README.md: -------------------------------------------------------------------------------- 1 | # Bastion Group Example 2 | 3 | This example will set up a group of bastion hosts using a managed instance group (MIG). 4 | 5 | ## Deploy 6 | 7 | Create a `terraform.tfvars` file with required variables similar to: 8 | 9 | ``` 10 | members = ["user:me@example.com"] 11 | project = "my-project" 12 | ``` 13 | 14 | Run the apply 15 | 16 | ``` 17 | terraform apply 18 | ``` 19 | 20 | ## Usage 21 | 22 | Since gcloud's start-iap-tunnel currently does not support anything but instance names as targets 23 | we have to do something akin to load balancing to get a random host of the instance group locally. 24 | In this case we have two hosts we want to randomly choose from and ssh to. 25 | 26 | ``` 27 | gcloud auth login 28 | 29 | INDEX=$((RANDOM % 2)) 30 | INSTANCE_URL=$(gcloud compute instance-groups list-instances bastion-mig --region us-west1 --format json | jq -r .[$INDEX].instance) 31 | ZONE=$(echo $INSTANCE_URL | cut -d'/' -f9) 32 | INSTANCE=$(echo $INSTANCE_URL | cut -d'/' -f11) 33 | gcloud compute ssh $INSTANCE --zone $ZONE 34 | ``` 35 | 36 | You should now be logged in as a user that looks like `ext_me_example_com` with the prefix of `ext` indicating you have logged in with OS Login. You should also notice the following line in standard out that indicates you are tunnelling through IAP instead of the public internet: 37 | 38 | ``` 39 | External IP address was not found; defaulting to using IAP tunneling. 40 | ``` 41 | 42 | You could also modify this such that users ssh to the same bastion each time. Although for more granular 43 | control over each instance, such as labelling per person or team, you should probably use the standard 44 | bastion-host module instead. 45 | 46 | 47 | ## Inputs 48 | 49 | | Name | Description | Type | Default | Required | 50 | |------|-------------|------|---------|:--------:| 51 | | members | List of members in the standard GCP form: user:{email}, serviceAccount:{email}, group:{email} | `list(string)` | `[]` | no | 52 | | project\_id | Project ID where to set up the instance and IAP tunneling | `any` | n/a | yes | 53 | 54 | ## Outputs 55 | 56 | | Name | Description | 57 | |------|-------------| 58 | | project\_id | n/a | 59 | 60 | 61 | -------------------------------------------------------------------------------- /examples/bastion_group/main.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 | module "iap_bastion_group" { 18 | source = "terraform-google-modules/bastion-host/google//modules/bastion-group" 19 | version = "~> 8.0" 20 | 21 | project = var.project_id 22 | region = "us-west1" 23 | zone = "us-west1-a" 24 | network = google_compute_network.network.self_link 25 | subnet = google_compute_subnetwork.subnet.self_link 26 | members = var.members 27 | target_size = 2 28 | } 29 | 30 | resource "google_compute_network" "network" { 31 | project = var.project_id 32 | name = "test-network-group" 33 | auto_create_subnetworks = false 34 | } 35 | 36 | resource "google_compute_subnetwork" "subnet" { 37 | project = var.project_id 38 | name = "test-subnet-group" 39 | region = "us-west1" 40 | ip_cidr_range = "10.128.0.0/20" 41 | network = google_compute_network.network.self_link 42 | private_ip_google_access = true 43 | } 44 | 45 | resource "google_compute_firewall" "allow_access_from_bastion" { 46 | project = var.project_id 47 | name = "allow-bastion-group-ssh" 48 | network = google_compute_network.network.self_link 49 | 50 | allow { 51 | protocol = "tcp" 52 | ports = ["22"] 53 | } 54 | 55 | # Allow SSH only from IAP Bastion 56 | source_service_accounts = [module.iap_bastion_group.service_account] 57 | } 58 | -------------------------------------------------------------------------------- /examples/bastion_group/outputs.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 | output "project_id" { 18 | value = var.project_id 19 | } 20 | -------------------------------------------------------------------------------- /examples/bastion_group/variables.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 | variable "members" { 18 | description = "List of members in the standard GCP form: user:{email}, serviceAccount:{email}, group:{email}" 19 | type = list(string) 20 | default = [] 21 | } 22 | 23 | variable "project_id" { 24 | description = "Project ID where to set up the instance and IAP tunneling" 25 | } 26 | -------------------------------------------------------------------------------- /examples/iap_tunneling/README.md: -------------------------------------------------------------------------------- 1 | # IAP Tunneling Example 2 | 3 | This example will create a testing VM and set up the firewall and IAM bindings to allow IAP connections to it for given members. 4 | 5 | ## Deploy 6 | 7 | Create a `terraform.tfvars` file with required variables similar to: 8 | 9 | ``` 10 | members = ["user:me@example.com"] 11 | project = "my-project" 12 | instance = "instance-1" 13 | zone = "us-central1-a" 14 | region = "us-central1" 15 | ``` 16 | 17 | Run the apply 18 | 19 | ``` 20 | terraform apply 21 | ``` 22 | 23 | ## Usage 24 | 25 | You can ssh to the VM instance with something similar to the following: 26 | 27 | ``` 28 | gcloud auth login 29 | gcloud compute ssh instance-1 --zone us-central1-a --project my-project 30 | ``` 31 | 32 | You should now be logged in as a user that looks like `ext_me_example_com` with the prefix of `ext` indicating you have logged in with OS Login. 33 | You should also notice the following line in standard out that indicates you are tunnelling through IAP instead of the public internet: 34 | 35 | ``` 36 | External IP address was not found; defaulting to using IAP tunneling. 37 | ``` 38 | 39 | 40 | ## Inputs 41 | 42 | | Name | Description | Type | Default | Required | 43 | |------|-------------|------|---------|:--------:| 44 | | members | List of members in the standard GCP form: user:{email}, serviceAccount:{email}, group:{email} | `list(string)` | n/a | yes | 45 | | project\_id | Project ID where to set up the instance and IAP tunneling | `any` | n/a | yes | 46 | 47 | ## Outputs 48 | 49 | | Name | Description | 50 | |------|-------------| 51 | | project\_id | n/a | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/iap_tunneling/main.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 | resource "google_compute_network" "network" { 18 | project = var.project_id 19 | name = "test-network-iap" 20 | auto_create_subnetworks = false 21 | } 22 | 23 | resource "google_compute_subnetwork" "subnet" { 24 | project = var.project_id 25 | name = "test-subnet-iap" 26 | region = "us-west1" 27 | ip_cidr_range = "10.127.0.0/20" 28 | network = google_compute_network.network.self_link 29 | private_ip_google_access = true 30 | } 31 | 32 | resource "google_service_account" "vm_sa" { 33 | project = var.project_id 34 | account_id = "iap-test-instance" 35 | display_name = "Service Account for VM" 36 | } 37 | 38 | # A testing VM to allow OS Login + IAP tunneling. 39 | module "instance_template" { 40 | source = "terraform-google-modules/vm/google//modules/instance_template" 41 | version = "~> 12.0" 42 | 43 | project_id = var.project_id 44 | machine_type = "n1-standard-1" 45 | subnetwork = google_compute_subnetwork.subnet.self_link 46 | service_account = { 47 | email = google_service_account.vm_sa.email 48 | scopes = ["cloud-platform"] 49 | } 50 | metadata = { 51 | enable-oslogin = "TRUE" 52 | } 53 | } 54 | 55 | resource "google_compute_instance_from_template" "vm" { 56 | name = "iap-test-instance" 57 | project = var.project_id 58 | zone = "us-west1-a" 59 | network_interface { 60 | subnetwork = google_compute_subnetwork.subnet.self_link 61 | } 62 | source_instance_template = module.instance_template.self_link 63 | } 64 | 65 | # Additional OS login IAM bindings. 66 | # https://cloud.google.com/compute/docs/instances/managing-instance-access#granting_os_login_iam_roles 67 | resource "google_service_account_iam_binding" "sa_user" { 68 | service_account_id = google_service_account.vm_sa.id 69 | role = "roles/iam.serviceAccountUser" 70 | members = var.members 71 | } 72 | 73 | resource "google_project_iam_member" "os_login_bindings" { 74 | for_each = toset(var.members) 75 | project = var.project_id 76 | role = "roles/compute.osLogin" 77 | member = each.key 78 | } 79 | 80 | module "iap_tunneling" { 81 | source = "terraform-google-modules/bastion-host/google//modules/iap-tunneling" 82 | version = "~> 8.0" 83 | 84 | fw_name_allow_ssh_from_iap = "test-allow-ssh-from-iap-to-tunnel" 85 | project = var.project_id 86 | network = google_compute_network.network.self_link 87 | service_accounts = [google_service_account.vm_sa.email] 88 | instances = [{ 89 | name = google_compute_instance_from_template.vm.name 90 | zone = "us-west1-a" 91 | }] 92 | members = var.members 93 | } 94 | -------------------------------------------------------------------------------- /examples/iap_tunneling/outputs.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 | output "project_id" { 18 | value = var.project_id 19 | } 20 | -------------------------------------------------------------------------------- /examples/iap_tunneling/variables.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 | variable "members" { 18 | description = "List of members in the standard GCP form: user:{email}, serviceAccount:{email}, group:{email}" 19 | type = list(string) 20 | } 21 | 22 | variable "project_id" { 23 | description = "Project ID where to set up the instance and IAP tunneling" 24 | } 25 | -------------------------------------------------------------------------------- /examples/simple_example/README.md: -------------------------------------------------------------------------------- 1 | # Simple Example 2 | 3 | This example will not set up the target hosts like the [Two Service Example](../two_service_example) but it will set up a basic network, subnet and bastion host for you to log into using IAP and OS Login. You'll notice that we create a firewall rule that allows the bastion to talk to the rest of the network on port 22 using the output of the bastion service account email for simplicity. This can and should be scoped down to allow access to specific hosts. 4 | 5 | ## Deploy 6 | 7 | Create a `terraform.tfvars` file with required variables similar to: 8 | 9 | ``` 10 | members = ["user:me@example.com"] 11 | project = "my-project" 12 | ``` 13 | 14 | Run the apply 15 | 16 | ``` 17 | terraform apply -var-file terraform.tfvars 18 | ``` 19 | 20 | ## Usage 21 | 22 | ``` 23 | gcloud auth login 24 | gcloud compute ssh bastion-vm 25 | ``` 26 | 27 | You should now be logged in as a user that looks like `ext_me_example_com` with the prefix of `ext` indicating you have logged in with OS Login. You should also notice the following line in standard out that indicates you are tunnelling through IAP instead of the public internet: 28 | 29 | ``` 30 | External IP address was not found; defaulting to using IAP tunneling. 31 | ``` 32 | 33 | 34 | ## Inputs 35 | 36 | | Name | Description | Type | Default | Required | 37 | |------|-------------|------|---------|:--------:| 38 | | members | List of members in the standard GCP form: user:{email}, serviceAccount:{email}, group:{email} | `list(string)` | `[]` | no | 39 | | project\_id | Project ID where the bastion will run | `string` | n/a | yes | 40 | 41 | ## Outputs 42 | 43 | | Name | Description | 44 | |------|-------------| 45 | | project\_id | n/a | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/simple_example/main.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 | module "iap_bastion" { 18 | source = "terraform-google-modules/bastion-host/google" 19 | version = "~> 8.0" 20 | 21 | project = var.project_id 22 | zone = "us-west1-a" 23 | network = google_compute_network.network.self_link 24 | subnet = google_compute_subnetwork.subnet.self_link 25 | members = var.members 26 | disk_labels = { 27 | "test-label" = "test-value" 28 | } 29 | } 30 | 31 | resource "google_compute_network" "network" { 32 | project = var.project_id 33 | name = "test-network" 34 | auto_create_subnetworks = false 35 | } 36 | 37 | resource "google_compute_subnetwork" "subnet" { 38 | project = var.project_id 39 | name = "test-subnet" 40 | region = "us-west1" 41 | ip_cidr_range = "10.127.0.0/20" 42 | network = google_compute_network.network.self_link 43 | private_ip_google_access = true 44 | } 45 | 46 | resource "google_compute_firewall" "allow_access_from_bastion" { 47 | project = var.project_id 48 | name = "allow-bastion-ssh" 49 | network = google_compute_network.network.self_link 50 | 51 | allow { 52 | protocol = "tcp" 53 | ports = ["22"] 54 | } 55 | 56 | # Allow SSH only from IAP Bastion 57 | source_service_accounts = [module.iap_bastion.service_account] 58 | } 59 | -------------------------------------------------------------------------------- /examples/simple_example/outputs.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 | output "project_id" { 18 | value = var.project_id 19 | } 20 | -------------------------------------------------------------------------------- /examples/simple_example/variables.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 | variable "members" { 18 | description = "List of members in the standard GCP form: user:{email}, serviceAccount:{email}, group:{email}" 19 | type = list(string) 20 | default = [] 21 | } 22 | 23 | variable "project_id" { 24 | description = "Project ID where the bastion will run" 25 | type = string 26 | } 27 | 28 | -------------------------------------------------------------------------------- /examples/two_service_example/README.md: -------------------------------------------------------------------------------- 1 | # Two Service Example 2 | 3 | This example illustrates how to use the `bastion-host` module. It illustrate an example where there are two services being deployed in a single project. Service A is deployed to two VMS (priv-host-a-1 and priv-host-a-2) and Service B is deployed to a single VM (priv-host-b-1). The bastion host module is deployed that will allow User A to access VM's for Service A, and User B to access Service B through the shared bastion host. You'll notice that we create a firewall rule that allows the bastion to talk to the rest of the network on port 22 using the output of the bastion service account email for simplicity. This can and should be scoped down to allow access to specific hosts. 4 | 5 | 6 | ## Deploy 7 | 8 | Create a `terraform.tfvars` file with required variables. Should look something like: 9 | 10 | ``` 11 | project = "my-project" 12 | user_a = "user:me@example.com" 13 | user_b = "user:someone@example.com" 14 | network = "projects/my-project/global/networks/default" 15 | subnet = "projects/rcanty-project-0529/regions/us-west1/subnetworks/default" 16 | ``` 17 | 18 | Run the apply 19 | 20 | ``` 21 | terraform apply -var-file terraform.tfvars 22 | ``` 23 | 24 | ## Usage 25 | 26 | After this module is deployed, you can test SSHing to the private hosts by following these steps: 27 | 28 | Login as User A: 29 | 30 | ``` 31 | gcloud auth login 32 | ``` 33 | 34 | If you have existing google_compute_engine ssh keys, ( ~/.ssh/google_compute_engine.pub ) back them up, otherwise skip this step 35 | 36 | ``` 37 | cd ~/.ssh # change working directory to ssh directory 38 | mv google_compute_engine.pub google_compute_engine_backup.pub # backup public key 39 | mv google_compute_engine google_compute_engine_backup_backup # backup private key 40 | ``` 41 | 42 | Update your gcloud config 43 | 44 | ``` 45 | gcloud config set project 46 | gcloud config set compute/region us-west1 47 | gcloud config set compute/zone us-west1-a 48 | ``` 49 | 50 | Generate new google compute engine keys and ssh over to bastion host 51 | 52 | ``` 53 | gcloud compute ssh bastion-vm 54 | ``` 55 | 56 | Exit out from bastion using `exit`. Then start SSH Agent and add your key to it: 57 | 58 | ``` 59 | eval "$(ssh-agent -s)" 60 | ssh-add ~/.ssh/google_compute_engine 61 | ``` 62 | 63 | SSH to private VM through bastion host 64 | 65 | ``` 66 | gcloud compute ssh bastion-vm --ssh-flag="-A" --command "ssh priv-host-a-1" -- -t 67 | ``` 68 | 69 | 70 | You can also try SSHing to the other host, priv-host-a-2. This should work. Try sshing to the B host, (priv-host-b-2) should fail. Try using user B, get another user to follow above steps. If you have access to a test account, you can use that as well, but make sure to backup the ssh keys from the steps above. 71 | 72 | 73 | ## Inputs 74 | 75 | | Name | Description | Type | Default | Required | 76 | |------|-------------|------|---------|:--------:| 77 | | network | Self link for the VPC network | `string` | n/a | yes | 78 | | project | The ID of the project in which to provision resources. | `string` | n/a | yes | 79 | | subnet | Self link for the Subnet within var.network | `string` | n/a | yes | 80 | | user\_a | User in the IAM policy format of user:{email} | `any` | n/a | yes | 81 | | user\_b | User in the IAM policy format of user:{email} | `any` | n/a | yes | 82 | | zone | n/a | `string` | `"us-west1-a"` | no | 83 | 84 | ## Outputs 85 | 86 | No outputs. 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/two_service_example/iam.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 | resource "google_service_account" "service_a" { 18 | project = var.project 19 | account_id = "service-a" 20 | display_name = "Service Account for Service A" 21 | } 22 | 23 | resource "google_service_account" "service_b" { 24 | project = var.project 25 | account_id = "service-b" 26 | display_name = "Service Account for Service B" 27 | } 28 | 29 | resource "google_compute_instance_iam_member" "alice_oslogin_1" { 30 | project = var.project 31 | zone = var.zone 32 | instance_name = google_compute_instance.priv_host_a_1.name 33 | role = "roles/compute.osLogin" 34 | member = var.user_a 35 | } 36 | 37 | resource "google_compute_instance_iam_member" "alice_oslogin_2" { 38 | project = var.project 39 | zone = var.zone 40 | instance_name = google_compute_instance.priv_host_a_2.name 41 | role = "roles/compute.osLogin" 42 | member = var.user_a 43 | } 44 | 45 | resource "google_service_account_iam_member" "gce_default_account_iam" { 46 | service_account_id = google_service_account.service_a.id 47 | role = "roles/iam.serviceAccountUser" 48 | member = var.user_a 49 | } 50 | 51 | resource "google_compute_instance_iam_member" "bdole_oslogin" { 52 | project = var.project 53 | zone = var.zone 54 | instance_name = google_compute_instance.priv_host_b_1.name 55 | role = "roles/compute.osLogin" 56 | member = var.user_b 57 | } 58 | 59 | resource "google_service_account_iam_member" "bdole_use_sa" { 60 | service_account_id = google_service_account.service_b.id 61 | role = "roles/iam.serviceAccountUser" 62 | member = var.user_b 63 | } 64 | -------------------------------------------------------------------------------- /examples/two_service_example/instances.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 | resource "google_compute_instance" "priv_host_a_1" { 18 | project = var.project 19 | zone = var.zone 20 | name = "priv-host-a-1" 21 | machine_type = "n1-standard-1" 22 | 23 | boot_disk { 24 | initialize_params { 25 | image = "debian-cloud/debian-9" 26 | } 27 | } 28 | 29 | network_interface { 30 | subnetwork = var.subnet 31 | } 32 | 33 | service_account { 34 | email = google_service_account.service_a.email 35 | scopes = ["cloud-platform"] 36 | } 37 | 38 | metadata = { 39 | enable-oslogin = "TRUE" 40 | } 41 | } 42 | 43 | resource "google_compute_instance" "priv_host_a_2" { 44 | project = var.project 45 | zone = var.zone 46 | name = "priv-host-a-2" 47 | machine_type = "n1-standard-1" 48 | 49 | boot_disk { 50 | initialize_params { 51 | image = "debian-cloud/debian-9" 52 | } 53 | } 54 | 55 | network_interface { 56 | subnetwork = var.subnet 57 | } 58 | 59 | service_account { 60 | email = google_service_account.service_a.email 61 | scopes = ["cloud-platform"] 62 | } 63 | 64 | metadata = { 65 | enable-oslogin = "TRUE" 66 | } 67 | } 68 | 69 | resource "google_compute_instance" "priv_host_b_1" { 70 | project = var.project 71 | zone = var.zone 72 | name = "priv-host-b-1" 73 | machine_type = "n1-standard-1" 74 | 75 | boot_disk { 76 | initialize_params { 77 | image = "debian-cloud/debian-9" 78 | } 79 | } 80 | 81 | network_interface { 82 | subnetwork = var.subnet 83 | } 84 | 85 | service_account { 86 | email = google_service_account.service_b.email 87 | scopes = ["cloud-platform"] 88 | } 89 | 90 | metadata = { 91 | enable-oslogin = "TRUE" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /examples/two_service_example/main.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 | provider "google" { 18 | } 19 | 20 | module "iap_bastion" { 21 | source = "terraform-google-modules/bastion-host/google" 22 | version = "~> 8.0" 23 | 24 | project = var.project 25 | subnet = var.subnet 26 | network = var.network 27 | zone = var.zone 28 | members = [var.user_a, var.user_b] 29 | } 30 | -------------------------------------------------------------------------------- /examples/two_service_example/test.yaml: -------------------------------------------------------------------------------- 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 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintTest 17 | metadata: 18 | name: two-service-example 19 | spec: 20 | skip: true 21 | -------------------------------------------------------------------------------- /examples/two_service_example/variables.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 | variable "project" { 18 | description = "The ID of the project in which to provision resources." 19 | type = string 20 | } 21 | 22 | variable "network" { 23 | description = "Self link for the VPC network" 24 | type = string 25 | } 26 | 27 | variable "subnet" { 28 | description = "Self link for the Subnet within var.network" 29 | type = string 30 | } 31 | 32 | variable "user_a" { 33 | description = "User in the IAM policy format of user:{email}" 34 | } 35 | 36 | variable "user_b" { 37 | description = "User in the IAM policy format of user:{email}" 38 | } 39 | 40 | variable "zone" { 41 | default = "us-west1-a" 42 | } 43 | -------------------------------------------------------------------------------- /main.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 | /****************************************** 18 | Project role id suffix configuration 19 | *****************************************/ 20 | resource "random_id" "random_role_id_suffix" { 21 | byte_length = 2 22 | } 23 | 24 | locals { 25 | base_role_id = "osLoginProjectGet" 26 | service_account_email = var.service_account_email == "" ? try(google_service_account.bastion_host[0].email, "") : var.service_account_email 27 | service_account_roles = var.service_account_email == "" ? toset(compact(concat( 28 | var.service_account_roles, 29 | var.service_account_roles_supplemental, 30 | ))) : [] 31 | temp_role_id = var.random_role_id ? format( 32 | "%s_%s", 33 | local.base_role_id, 34 | random_id.random_role_id_suffix.hex, 35 | ) : local.base_role_id 36 | } 37 | 38 | resource "google_service_account" "bastion_host" { 39 | count = var.service_account_email == "" ? 1 : 0 40 | project = var.project 41 | account_id = var.service_account_name 42 | display_name = "Service Account for Bastion" 43 | } 44 | 45 | module "instance_template" { 46 | source = "terraform-google-modules/vm/google//modules/instance_template" 47 | version = "~> 12.0" 48 | 49 | name_prefix = var.name_prefix 50 | project_id = var.project 51 | machine_type = var.machine_type 52 | disk_size_gb = var.disk_size_gb 53 | disk_type = var.disk_type 54 | disk_labels = var.disk_labels 55 | subnetwork = var.subnet 56 | subnetwork_project = var.host_project 57 | additional_networks = var.additional_networks 58 | region = var.region 59 | 60 | service_account = { 61 | email = local.service_account_email 62 | scopes = var.scopes 63 | } 64 | enable_shielded_vm = var.shielded_vm 65 | source_image = var.image 66 | source_image_family = var.image_family 67 | source_image_project = var.image_project 68 | startup_script = var.startup_script 69 | preemptible = var.preemptible 70 | can_ip_forward = var.can_ip_forward ? "true" : "false" 71 | 72 | tags = var.tags 73 | labels = var.labels 74 | 75 | metadata = merge( 76 | var.metadata, 77 | { 78 | enable-oslogin = "TRUE" 79 | } 80 | ) 81 | } 82 | 83 | resource "google_compute_instance_from_template" "bastion_vm" { 84 | count = var.create_instance_from_template ? 1 : 0 85 | name = var.name 86 | project = var.project 87 | zone = var.zone 88 | labels = var.labels 89 | 90 | network_interface { 91 | subnetwork = var.subnet 92 | subnetwork_project = var.host_project != "" ? var.host_project : var.project 93 | network_ip = var.network_ip 94 | 95 | dynamic "access_config" { 96 | for_each = var.external_ip ? var.access_config : [] 97 | content { 98 | nat_ip = access_config.value["nat_ip"] 99 | public_ptr_domain_name = access_config.value["public_ptr_domain_name"] 100 | network_tier = access_config.value["network_tier"] 101 | } 102 | } 103 | } 104 | 105 | source_instance_template = module.instance_template.self_link 106 | } 107 | 108 | module "iap_tunneling" { 109 | source = "./modules/iap-tunneling" 110 | 111 | host_project = var.host_project 112 | project = var.project 113 | additional_ports = var.additional_ports 114 | fw_name_allow_ssh_from_iap = var.fw_name_allow_ssh_from_iap 115 | network = var.network 116 | service_accounts = [local.service_account_email] 117 | instances = var.create_instance_from_template ? [{ 118 | name = try(google_compute_instance_from_template.bastion_vm[0].name, "") 119 | zone = var.zone 120 | }] : [] 121 | members = var.members 122 | create_firewall_rule = var.create_firewall_rule 123 | } 124 | 125 | resource "google_service_account_iam_binding" "bastion_sa_user" { 126 | count = var.service_account_email == "" ? 1 : 0 127 | service_account_id = google_service_account.bastion_host[0].id 128 | role = "roles/iam.serviceAccountUser" 129 | members = var.members 130 | } 131 | 132 | resource "google_project_iam_member" "bastion_sa_bindings" { 133 | for_each = local.service_account_roles 134 | 135 | project = var.project 136 | role = each.key 137 | member = "serviceAccount:${local.service_account_email}" 138 | } 139 | 140 | # If you are practicing least privilege, to enable instance level OS Login, you 141 | # still need the compute.projects.get permission on the project level. The other 142 | # predefined roles grant additional permissions that aren't needed 143 | resource "google_project_iam_custom_role" "compute_os_login_viewer" { 144 | count = var.service_account_email == "" ? 1 : 0 145 | project = var.project 146 | role_id = local.temp_role_id 147 | title = "OS Login Project Get Role" 148 | description = "From Terraform: iap-bastion module custom role for more fine grained scoping of permissions" 149 | permissions = ["compute.projects.get"] 150 | } 151 | 152 | resource "google_project_iam_member" "bastion_oslogin_bindings" { 153 | count = var.service_account_email == "" ? 1 : 0 154 | project = var.project 155 | role = "projects/${var.project}/roles/${google_project_iam_custom_role.compute_os_login_viewer[0].role_id}" 156 | member = "serviceAccount:${local.service_account_email}" 157 | } 158 | -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 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 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-bastion-host 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | title: terraform-google-bastion-host 23 | source: 24 | repo: https://github.com/terraform-google-modules/terraform-google-bastion-host 25 | sourceType: git 26 | version: 8.0.0 27 | actuationTool: 28 | type: Terraform 29 | version: '>=0.13' 30 | subBlueprints: 31 | - name: bastion-group 32 | location: modules/bastion-group 33 | - name: iap-tunneling 34 | location: modules/iap-tunneling 35 | examples: 36 | - name: bastion_group 37 | location: examples/bastion_group 38 | - name: iap_tunneling 39 | location: examples/iap_tunneling 40 | - name: simple_example 41 | location: examples/simple_example 42 | - name: two_service_example 43 | location: examples/two_service_example 44 | variables: 45 | - name: access_config 46 | description: Access configs for network, nat_ip and DNS 47 | type: |- 48 | list(object({ 49 | network_tier = string 50 | nat_ip = string 51 | public_ptr_domain_name = string 52 | })) 53 | default: 54 | - nat_ip: "" 55 | network_tier: PREMIUM 56 | public_ptr_domain_name: "" 57 | required: false 58 | - name: additional_networks 59 | description: Additional network interface details for the instance template, if any. 60 | type: |- 61 | list(object({ 62 | network = string 63 | subnetwork = string 64 | subnetwork_project = string 65 | network_ip = string 66 | access_config = list(object({ 67 | nat_ip = string 68 | network_tier = string 69 | })) 70 | })) 71 | default: [] 72 | required: false 73 | - name: additional_ports 74 | description: A list of additional ports/ranges to open access to on the instances from IAP. 75 | type: list(string) 76 | default: [] 77 | required: false 78 | - name: create_firewall_rule 79 | description: If we need to create the firewall rule or not. 80 | type: bool 81 | default: true 82 | required: false 83 | - name: create_instance_from_template 84 | description: Whether to create and instance from the template or not. If false, no instance is created, but the instance template is created and usable by a MIG 85 | type: bool 86 | default: true 87 | required: false 88 | - name: disk_size_gb 89 | description: Boot disk size in GB 90 | type: number 91 | default: 100 92 | required: false 93 | - name: disk_type 94 | description: Boot disk type, can be either pd-ssd, local-ssd, or pd-standard 95 | type: string 96 | default: pd-standard 97 | required: false 98 | - name: external_ip 99 | description: Set to true if an ephemeral or static external IP/DNS is required, must also set access_config if true 100 | type: bool 101 | default: false 102 | required: false 103 | - name: fw_name_allow_ssh_from_iap 104 | description: Firewall rule name for allowing SSH from IAP 105 | type: string 106 | default: allow-ssh-from-iap-to-tunnel 107 | required: false 108 | - name: host_project 109 | description: The network host project ID 110 | type: string 111 | default: "" 112 | required: false 113 | - name: image 114 | description: Source image for the Bastion. If image is not specified, image_family will be used (which is the default). 115 | type: string 116 | default: "" 117 | required: false 118 | - name: image_family 119 | description: Source image family for the Bastion. 120 | type: string 121 | default: debian-12 122 | required: false 123 | - name: image_project 124 | description: Project where the source image for the Bastion comes from 125 | type: string 126 | default: debian-cloud 127 | required: false 128 | - name: labels 129 | description: Key-value map of labels to assign to the bastion host 130 | type: map(any) 131 | default: {} 132 | required: false 133 | - name: machine_type 134 | description: Instance type for the Bastion host 135 | type: string 136 | default: n1-standard-1 137 | required: false 138 | - name: members 139 | description: List of IAM resources to allow access to the bastion host 140 | type: list(string) 141 | default: [] 142 | required: false 143 | - name: metadata 144 | description: Key-value map of additional metadata to assign to the instances 145 | type: map(string) 146 | default: {} 147 | required: false 148 | - name: name 149 | description: Name of the Bastion instance 150 | type: string 151 | default: bastion-vm 152 | required: false 153 | - name: name_prefix 154 | description: Name prefix for instance template 155 | type: string 156 | default: bastion-instance-template 157 | required: false 158 | - name: network 159 | description: Self link for the network on which the Bastion should live 160 | type: string 161 | required: true 162 | - name: preemptible 163 | description: Allow the instance to be preempted 164 | type: bool 165 | default: false 166 | required: false 167 | - name: project 168 | description: The project ID to deploy to 169 | type: string 170 | required: true 171 | - name: random_role_id 172 | description: Enables role random id generation. 173 | type: bool 174 | default: true 175 | required: false 176 | - name: scopes 177 | description: List of scopes to attach to the bastion host 178 | type: list(string) 179 | default: 180 | - cloud-platform 181 | required: false 182 | - name: service_account_email 183 | description: If set, the service account and its permissions will not be created. The service account being passed in should have at least the roles listed in the `service_account_roles` variable so that logging and OS Login work as expected. 184 | type: string 185 | default: "" 186 | required: false 187 | - name: service_account_name 188 | description: Account ID for the service account 189 | type: string 190 | default: bastion 191 | required: false 192 | - name: service_account_roles 193 | description: List of IAM roles to assign to the service account. 194 | type: list(string) 195 | default: 196 | - roles/logging.logWriter 197 | - roles/monitoring.metricWriter 198 | - roles/monitoring.viewer 199 | - roles/compute.osLogin 200 | required: false 201 | - name: service_account_roles_supplemental 202 | description: An additional list of roles to assign to the bastion if desired 203 | type: list(string) 204 | default: [] 205 | required: false 206 | - name: shielded_vm 207 | description: Enable shielded VM on the bastion host (recommended) 208 | type: bool 209 | default: true 210 | required: false 211 | - name: startup_script 212 | description: Render a startup script with a template. 213 | type: string 214 | default: "" 215 | required: false 216 | - name: subnet 217 | description: Self link for the subnet on which the Bastion should live. Can be private when using IAP 218 | type: string 219 | required: true 220 | - name: tags 221 | description: Network tags, provided as a list 222 | type: list(string) 223 | default: [] 224 | required: false 225 | - name: zone 226 | description: The primary zone where the bastion host will live 227 | type: string 228 | default: us-central1-a 229 | required: false 230 | outputs: 231 | - name: hostname 232 | description: Host name of the bastion 233 | - name: instance_template 234 | description: Self link of the bastion instance template for use with a MIG 235 | - name: ip_address 236 | description: Internal IP address of the bastion host 237 | - name: self_link 238 | description: Self link of the bastion host 239 | - name: service_account 240 | description: The email for the service account created for the bastion host 241 | roles: 242 | - level: Project 243 | roles: 244 | - roles/owner 245 | - roles/compute.admin 246 | - roles/compute.networkAdmin 247 | - roles/iam.serviceAccountUser 248 | - roles/compute.instanceAdmin 249 | - roles/compute.osLogin 250 | services: 251 | - cloudresourcemanager.googleapis.com 252 | - serviceusage.googleapis.com 253 | - compute.googleapis.com 254 | - iam.googleapis.com 255 | - oslogin.googleapis.com 256 | - iap.googleapis.com 257 | -------------------------------------------------------------------------------- /modules/bastion-group/README.md: -------------------------------------------------------------------------------- 1 | # bastion-group 2 | 3 | This module will generate a managed instance group of bastion host VMs compatible with [OS Login](https://cloud.google.com/compute/docs/oslogin/) and [IAP Tunneling](https://cloud.google.com/iap/) that can be used to access internal VMs. 4 | 5 | This module will: 6 | 7 | - Create a dedicated service account for the bastion host 8 | - Create managed instance group of GCE instances to be the bastion host 9 | - Create a firewall rule to allow TCP:22 SSH access from the IAP to the bastion 10 | - Necessary IAM bindings to allow IAP and OS Logins from specified members 11 | 12 | ## Usage 13 | 14 | Basic usage of this module is as follows: 15 | 16 | ```hcl 17 | module "bastion_group" { 18 | source = "terraform-google-modules/bastion-host/google//modules/bastion-group" 19 | 20 | target_size = 2 21 | project = var.project 22 | region = var.region 23 | zone = var.zone 24 | network = google_compute_network.net.self_link 25 | subnet = google_compute_subnetwork.net.self_link 26 | members = [ 27 | "group:devs@example.com", 28 | "user:me@example.com", 29 | ] 30 | } 31 | ``` 32 | 33 | Once the bastion group is created, you can search for the newly created 34 | instances with something similar to the following: 35 | 36 | ``` 37 | $ gcloud compute instance-groups list-instances bastion-mig --region us-west1 38 | NAME ZONE STATUS 39 | bastion-9qgq us-west1-c RUNNING 40 | bastion-rtv4 us-west1-b RUNNING 41 | ``` 42 | 43 | 44 | Functional example is included in the 45 | [examples](../../examples/) directory. 46 | 47 | ## Requirements 48 | 49 | These sections describe requirements for using this module. 50 | 51 | ### Software 52 | 53 | The following dependencies must be available: 54 | 55 | - [Terraform][terraform] v0.12 56 | - [Terraform Provider for GCP][terraform-provider-gcp] 57 | 58 | ### APIs 59 | 60 | A project with the following APIs enabled must be used to host the 61 | resources of this module: 62 | 63 | - Google Cloud Storage JSON API: `storage-api.googleapis.com` 64 | - Compute Engine API: `compute.googleapis.com` 65 | - Cloud Identity-Aware Proxy API: `iap.googleapis.com` 66 | - OS Login API: `oslogin.googleapis.com` 67 | 68 | The [Project Factory module][project-factory-module] can be used to 69 | provision a project with the necessary APIs enabled. 70 | 71 | 72 | ## Inputs 73 | 74 | | Name | Description | Type | Default | Required | 75 | |------|-------------|------|---------|:--------:| 76 | | additional\_networks | Additional network interface details for the instance template, if any. |
list(object({
network = string
subnetwork = string
subnetwork_project = string
network_ip = string
nic_type = string
stack_type = string
queue_count = number
access_config = list(object({
nat_ip = string
network_tier = string
}))
ipv6_access_config = list(object({
network_tier = string
}))
alias_ip_range = list(object({
ip_cidr_range = string
subnetwork_range_name = string
}))
}))
| `[]` | no | 77 | | additional\_ports | A list of additional ports/ranges to open access to on the instances from IAP. | `list(string)` | `[]` | no | 78 | | fw\_name\_allow\_ssh\_from\_health\_check\_cidrs | Firewall rule name for allowing Health Checks | `string` | `"allow-ssh-from-health-check-cidrs"` | no | 79 | | fw\_name\_allow\_ssh\_from\_iap | Firewall rule name for allowing SSH from IAP | `string` | `"allow-ssh-from-iap-to-bastion-group"` | no | 80 | | health\_check | Health check config for the mig. |
object({
type = string
initial_delay_sec = number
check_interval_sec = number
healthy_threshold = number
timeout_sec = number
unhealthy_threshold = number
response = string
proxy_header = string
port = number
request = string
enable_logging = bool

# Unused fields.
request_path = string
host = string
})
|
{
"check_interval_sec": 30,
"enable_logging": false,
"healthy_threshold": 1,
"host": "",
"initial_delay_sec": 30,
"port": 22,
"proxy_header": "NONE",
"request": "",
"request_path": "",
"response": "",
"timeout_sec": 10,
"type": "tcp",
"unhealthy_threshold": 5
}
| no | 81 | | host\_project | The network host project ID | `string` | `""` | no | 82 | | image\_family | Source image family for the Bastion. | `string` | `"debian-12"` | no | 83 | | image\_project | Project where the source image for the Bastion comes from | `string` | `"debian-cloud"` | no | 84 | | labels | Key-value map of labels to assign to the bastion host | `map(any)` | `{}` | no | 85 | | machine\_type | Instance type for the Bastion host | `string` | `"n1-standard-1"` | no | 86 | | members | List of IAM resources to allow access to the bastion host | `list(string)` | `[]` | no | 87 | | metadata | Key-value map of additional metadata to assign to the instances | `map(string)` | `{}` | no | 88 | | name | Name prefix of bastion instances | `string` | `"bastion"` | no | 89 | | network | Self link for the network on which the Bastion should live | `string` | n/a | yes | 90 | | project | The project ID to deploy to | `string` | n/a | yes | 91 | | random\_role\_id | Enables role random id generation. | `bool` | `true` | no | 92 | | region | The primary region where the bastion host will live | `string` | `"us-central1"` | no | 93 | | scopes | List of scopes to attach to the bastion host | `list(string)` |
[
"cloud-platform"
]
| no | 94 | | service\_account\_email | If set, the service account and its permissions will not be created. The service account being passed in should have at least the roles listed in the parent module `service_account_roles` variable so that logging and OS Login work as expected. | `string` | `""` | no | 95 | | service\_account\_name | Account ID for the service account | `string` | `"bastion-group"` | no | 96 | | service\_account\_roles | List of IAM roles to assign to the service account. | `list(string)` |
[
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
"roles/monitoring.viewer",
"roles/compute.osLogin"
]
| no | 97 | | service\_account\_roles\_supplemental | An additional list of roles to assign to the bastion if desired | `list(string)` |
[
""
]
| no | 98 | | shielded\_vm | Enable shielded VM on the bastion host (recommended) | `bool` | `true` | no | 99 | | startup\_script | Render a startup script with a template. | `string` | `""` | no | 100 | | subnet | Self link for the subnet on which the Bastion should live. Can be private when using IAP | `string` | n/a | yes | 101 | | tags | Network tags, provided as a list | `list(string)` | `[]` | no | 102 | | target\_size | Number of instances to create | `number` | `1` | no | 103 | | zone | The primary zone where the bastion host will live | `string` | `"us-central1-a"` | no | 104 | 105 | ## Outputs 106 | 107 | | Name | Description | 108 | |------|-------------| 109 | | instance\_group | Instance-group url of managed instance group | 110 | | self\_link | Name of the bastion MIG | 111 | | service\_account | The email for the service account created for the bastion host | 112 | 113 | 114 | 115 | ## Contributing 116 | 117 | Refer to the [contribution guidelines](./CONTRIBUTING.md) for 118 | information on contributing to this module. 119 | 120 | [iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google 121 | [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google 122 | [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html 123 | [terraform]: https://www.terraform.io/downloads.html 124 | -------------------------------------------------------------------------------- /modules/bastion-group/main.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 | module "iap_bastion" { 18 | source = "../.." 19 | image_family = var.image_family 20 | image_project = var.image_project 21 | tags = var.tags 22 | labels = var.labels 23 | machine_type = var.machine_type 24 | members = var.members 25 | name = var.name 26 | network = var.network 27 | project = var.project 28 | host_project = var.host_project 29 | scopes = var.scopes 30 | service_account_name = var.service_account_name 31 | service_account_email = var.service_account_email 32 | service_account_roles = var.service_account_roles 33 | service_account_roles_supplemental = var.service_account_roles_supplemental 34 | shielded_vm = var.shielded_vm 35 | startup_script = var.startup_script 36 | subnet = var.subnet 37 | additional_networks = var.additional_networks 38 | additional_ports = var.additional_ports 39 | zone = var.zone 40 | random_role_id = var.random_role_id 41 | fw_name_allow_ssh_from_iap = var.fw_name_allow_ssh_from_iap 42 | create_instance_from_template = false 43 | metadata = var.metadata 44 | } 45 | 46 | module "mig" { 47 | source = "terraform-google-modules/vm/google//modules/mig" 48 | version = "~> 12.0" 49 | 50 | project_id = var.project 51 | region = var.region 52 | target_size = var.target_size 53 | hostname = var.name 54 | health_check = var.health_check 55 | instance_template = module.iap_bastion.instance_template 56 | } 57 | 58 | resource "google_compute_firewall" "allow_from_iap_to_bastion" { 59 | project = var.host_project != "" ? var.host_project : var.project 60 | name = var.fw_name_allow_ssh_from_health_check_cidrs 61 | network = var.network 62 | 63 | allow { 64 | protocol = "tcp" 65 | ports = ["22"] 66 | } 67 | 68 | # Allow access to the bastion instances from the Health Check endpoints 69 | source_ranges = [ 70 | "35.191.0.0/16", 71 | "130.211.0.0/22" 72 | ] 73 | target_service_accounts = [module.iap_bastion.service_account] 74 | } 75 | 76 | # TODO: Currently gcloud compute start-iap-tunnel does not support 77 | # anything but instances. Add in ILB code when b/147258412 is fixed. 78 | # (2020-01-07) Ryan Canty 79 | -------------------------------------------------------------------------------- /modules/bastion-group/metadata.yaml: -------------------------------------------------------------------------------- 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 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-bastion-host 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | title: bastion-group 23 | source: 24 | repo: https://github.com/terraform-google-modules/terraform-google-bastion-host 25 | sourceType: git 26 | version: 8.0.0 27 | actuationTool: 28 | type: Terraform 29 | version: '>=0.13' 30 | examples: 31 | - name: bastion_group 32 | location: examples/bastion_group 33 | - name: iap_tunneling 34 | location: examples/iap_tunneling 35 | - name: simple_example 36 | location: examples/simple_example 37 | - name: two_service_example 38 | location: examples/two_service_example 39 | variables: 40 | - name: additional_networks 41 | description: Additional network interface details for the instance template, if any. 42 | type: |- 43 | list(object({ 44 | network = string 45 | subnetwork = string 46 | subnetwork_project = string 47 | network_ip = string 48 | access_config = list(object({ 49 | nat_ip = string 50 | network_tier = string 51 | })) 52 | })) 53 | default: [] 54 | required: false 55 | - name: fw_name_allow_ssh_from_health_check_cidrs 56 | description: Firewall rule name for allowing Health Checks 57 | type: string 58 | default: allow-ssh-from-health-check-cidrs 59 | required: false 60 | - name: fw_name_allow_ssh_from_iap 61 | description: Firewall rule name for allowing SSH from IAP 62 | type: string 63 | default: allow-ssh-from-iap-to-bastion-group 64 | required: false 65 | - name: health_check 66 | description: Health check config for the mig. 67 | type: |- 68 | object({ 69 | type = string 70 | initial_delay_sec = number 71 | check_interval_sec = number 72 | healthy_threshold = number 73 | timeout_sec = number 74 | unhealthy_threshold = number 75 | response = string 76 | proxy_header = string 77 | port = number 78 | request = string 79 | 80 | # Unused fields. 81 | request_path = string 82 | host = string 83 | }) 84 | default: 85 | check_interval_sec: 30 86 | healthy_threshold: 1 87 | host: "" 88 | initial_delay_sec: 30 89 | port: 22 90 | proxy_header: NONE 91 | request: "" 92 | request_path: "" 93 | response: "" 94 | timeout_sec: 10 95 | type: tcp 96 | unhealthy_threshold: 5 97 | required: false 98 | - name: host_project 99 | description: The network host project ID 100 | type: string 101 | default: "" 102 | required: false 103 | - name: image_family 104 | description: Source image family for the Bastion. 105 | type: string 106 | default: debian-12 107 | required: false 108 | - name: image_project 109 | description: Project where the source image for the Bastion comes from 110 | type: string 111 | default: debian-cloud 112 | required: false 113 | - name: labels 114 | description: Key-value map of labels to assign to the bastion host 115 | type: map(any) 116 | default: {} 117 | required: false 118 | - name: machine_type 119 | description: Instance type for the Bastion host 120 | type: string 121 | default: n1-standard-1 122 | required: false 123 | - name: members 124 | description: List of IAM resources to allow access to the bastion host 125 | type: list(string) 126 | default: [] 127 | required: false 128 | - name: metadata 129 | description: Key-value map of additional metadata to assign to the instances 130 | type: map(string) 131 | default: {} 132 | required: false 133 | - name: name 134 | description: Name prefix of bastion instances 135 | type: string 136 | default: bastion 137 | required: false 138 | - name: network 139 | description: Self link for the network on which the Bastion should live 140 | type: string 141 | required: true 142 | - name: project 143 | description: The project ID to deploy to 144 | type: string 145 | required: true 146 | - name: random_role_id 147 | description: Enables role random id generation. 148 | type: bool 149 | default: true 150 | required: false 151 | - name: region 152 | description: The primary region where the bastion host will live 153 | type: string 154 | default: us-central1 155 | required: false 156 | - name: scopes 157 | description: List of scopes to attach to the bastion host 158 | type: list(string) 159 | default: 160 | - cloud-platform 161 | required: false 162 | - name: service_account_email 163 | description: If set, the service account and its permissions will not be created. The service account being passed in should have at least the roles listed in the parent module `service_account_roles` variable so that logging and OS Login work as expected. 164 | type: string 165 | default: "" 166 | required: false 167 | - name: service_account_name 168 | description: Account ID for the service account 169 | type: string 170 | default: bastion-group 171 | required: false 172 | - name: service_account_roles 173 | description: List of IAM roles to assign to the service account. 174 | type: list(string) 175 | default: 176 | - roles/logging.logWriter 177 | - roles/monitoring.metricWriter 178 | - roles/monitoring.viewer 179 | - roles/compute.osLogin 180 | required: false 181 | - name: service_account_roles_supplemental 182 | description: An additional list of roles to assign to the bastion if desired 183 | type: list(string) 184 | default: 185 | - "" 186 | required: false 187 | - name: shielded_vm 188 | description: Enable shielded VM on the bastion host (recommended) 189 | type: bool 190 | default: true 191 | required: false 192 | - name: startup_script 193 | description: Render a startup script with a template. 194 | type: string 195 | default: "" 196 | required: false 197 | - name: subnet 198 | description: Self link for the subnet on which the Bastion should live. Can be private when using IAP 199 | type: string 200 | required: true 201 | - name: tags 202 | description: Network tags, provided as a list 203 | type: list(string) 204 | default: [] 205 | required: false 206 | - name: target_size 207 | description: Number of instances to create 208 | type: number 209 | default: 1 210 | required: false 211 | - name: zone 212 | description: The primary zone where the bastion host will live 213 | type: string 214 | default: us-central1-a 215 | required: false 216 | outputs: 217 | - name: instance_group 218 | description: Instance-group url of managed instance group 219 | - name: self_link 220 | description: Name of the bastion MIG 221 | - name: service_account 222 | description: The email for the service account created for the bastion host 223 | roles: 224 | - level: Project 225 | roles: 226 | - roles/owner 227 | - roles/compute.admin 228 | - roles/compute.networkAdmin 229 | - roles/iam.serviceAccountUser 230 | - roles/compute.instanceAdmin 231 | - roles/compute.osLogin 232 | services: 233 | - cloudresourcemanager.googleapis.com 234 | - serviceusage.googleapis.com 235 | - compute.googleapis.com 236 | - iam.googleapis.com 237 | - oslogin.googleapis.com 238 | - iap.googleapis.com 239 | -------------------------------------------------------------------------------- /modules/bastion-group/outputs.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 | output "service_account" { 18 | description = "The email for the service account created for the bastion host" 19 | value = module.iap_bastion.service_account 20 | } 21 | 22 | output "self_link" { 23 | description = "Name of the bastion MIG" 24 | value = module.mig.self_link 25 | } 26 | 27 | output "instance_group" { 28 | description = "Instance-group url of managed instance group" 29 | value = module.mig.instance_group 30 | } 31 | -------------------------------------------------------------------------------- /modules/bastion-group/variables.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 | variable "target_size" { 17 | description = "Number of instances to create" 18 | type = number 19 | default = 1 20 | } 21 | 22 | variable "image_family" { 23 | description = "Source image family for the Bastion." 24 | type = string 25 | default = "debian-12" 26 | } 27 | 28 | variable "image_project" { 29 | description = "Project where the source image for the Bastion comes from" 30 | type = string 31 | default = "debian-cloud" 32 | } 33 | 34 | variable "tags" { 35 | type = list(string) 36 | description = "Network tags, provided as a list" 37 | default = [] 38 | } 39 | 40 | variable "labels" { 41 | description = "Key-value map of labels to assign to the bastion host" 42 | type = map(any) 43 | default = {} 44 | } 45 | 46 | variable "machine_type" { 47 | description = "Instance type for the Bastion host" 48 | type = string 49 | default = "n1-standard-1" 50 | } 51 | 52 | variable "members" { 53 | description = "List of IAM resources to allow access to the bastion host" 54 | type = list(string) 55 | default = [] 56 | } 57 | 58 | variable "name" { 59 | description = "Name prefix of bastion instances" 60 | type = string 61 | default = "bastion" 62 | } 63 | 64 | variable "network" { 65 | description = "Self link for the network on which the Bastion should live" 66 | type = string 67 | } 68 | 69 | variable "project" { 70 | description = "The project ID to deploy to" 71 | type = string 72 | } 73 | 74 | variable "health_check" { 75 | description = "Health check config for the mig." 76 | type = object({ 77 | type = string 78 | initial_delay_sec = number 79 | check_interval_sec = number 80 | healthy_threshold = number 81 | timeout_sec = number 82 | unhealthy_threshold = number 83 | response = string 84 | proxy_header = string 85 | port = number 86 | request = string 87 | enable_logging = bool 88 | 89 | # Unused fields. 90 | request_path = string 91 | host = string 92 | }) 93 | default = { 94 | type = "tcp" 95 | initial_delay_sec = 30 96 | check_interval_sec = 30 97 | healthy_threshold = 1 98 | timeout_sec = 10 99 | unhealthy_threshold = 5 100 | response = "" 101 | proxy_header = "NONE" 102 | port = 22 103 | request = "" 104 | enable_logging = false 105 | 106 | # Unused fields. 107 | request_path = "" 108 | host = "" 109 | } 110 | } 111 | 112 | variable "host_project" { 113 | description = "The network host project ID" 114 | type = string 115 | default = "" 116 | } 117 | 118 | variable "region" { 119 | description = "The primary region where the bastion host will live" 120 | type = string 121 | default = "us-central1" 122 | } 123 | 124 | variable "scopes" { 125 | description = "List of scopes to attach to the bastion host" 126 | type = list(string) 127 | default = ["cloud-platform"] 128 | } 129 | 130 | variable "service_account_roles" { 131 | description = "List of IAM roles to assign to the service account." 132 | type = list(string) 133 | default = [ 134 | "roles/logging.logWriter", 135 | "roles/monitoring.metricWriter", 136 | "roles/monitoring.viewer", 137 | "roles/compute.osLogin", 138 | ] 139 | } 140 | 141 | variable "service_account_roles_supplemental" { 142 | description = "An additional list of roles to assign to the bastion if desired" 143 | type = list(string) 144 | default = [""] 145 | } 146 | 147 | variable "service_account_name" { 148 | description = "Account ID for the service account" 149 | type = string 150 | default = "bastion-group" 151 | } 152 | 153 | variable "service_account_email" { 154 | description = "If set, the service account and its permissions will not be created. The service account being passed in should have at least the roles listed in the parent module `service_account_roles` variable so that logging and OS Login work as expected." 155 | default = "" 156 | type = string 157 | } 158 | 159 | variable "shielded_vm" { 160 | description = "Enable shielded VM on the bastion host (recommended)" 161 | default = true 162 | type = bool 163 | } 164 | 165 | variable "startup_script" { 166 | description = "Render a startup script with a template." 167 | type = string 168 | default = "" 169 | } 170 | 171 | variable "subnet" { 172 | description = "Self link for the subnet on which the Bastion should live. Can be private when using IAP" 173 | type = string 174 | } 175 | 176 | variable "zone" { 177 | description = "The primary zone where the bastion host will live" 178 | type = string 179 | default = "us-central1-a" 180 | } 181 | 182 | variable "random_role_id" { 183 | description = "Enables role random id generation." 184 | type = bool 185 | default = true 186 | } 187 | 188 | variable "fw_name_allow_ssh_from_health_check_cidrs" { 189 | description = "Firewall rule name for allowing Health Checks" 190 | type = string 191 | default = "allow-ssh-from-health-check-cidrs" 192 | } 193 | 194 | variable "fw_name_allow_ssh_from_iap" { 195 | description = "Firewall rule name for allowing SSH from IAP" 196 | type = string 197 | default = "allow-ssh-from-iap-to-bastion-group" 198 | } 199 | 200 | variable "additional_ports" { 201 | description = "A list of additional ports/ranges to open access to on the instances from IAP." 202 | type = list(string) 203 | default = [] 204 | } 205 | 206 | variable "additional_networks" { 207 | description = "Additional network interface details for the instance template, if any." 208 | default = [] 209 | type = list(object({ 210 | network = string 211 | subnetwork = string 212 | subnetwork_project = string 213 | network_ip = string 214 | nic_type = string 215 | stack_type = string 216 | queue_count = number 217 | access_config = list(object({ 218 | nat_ip = string 219 | network_tier = string 220 | })) 221 | ipv6_access_config = list(object({ 222 | network_tier = string 223 | })) 224 | alias_ip_range = list(object({ 225 | ip_cidr_range = string 226 | subnetwork_range_name = string 227 | })) 228 | })) 229 | } 230 | 231 | variable "metadata" { 232 | type = map(string) 233 | description = "Key-value map of additional metadata to assign to the instances" 234 | default = {} 235 | } 236 | -------------------------------------------------------------------------------- /modules/bastion-group/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 | terraform { 17 | required_version = ">=0.13" 18 | required_providers { 19 | google = { 20 | source = "hashicorp/google" 21 | version = ">= 3.53, < 7" 22 | } 23 | google-beta = { 24 | source = "hashicorp/google-beta" 25 | version = ">= 3.53, < 7" 26 | } 27 | random = { 28 | source = "hashicorp/random" 29 | } 30 | } 31 | provider_meta "google" { 32 | module_name = "blueprints/terraform/terraform-google-bastion-host:bastion-group/v8.0.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /modules/iap-tunneling/README.md: -------------------------------------------------------------------------------- 1 | # iap-tunneling 2 | 3 | This module will create firewall rules and IAM bindings to allow TCP forwarding using 4 | [Identity-Aware Proxy (IAP) Tunneling](https://cloud.google.com/iap/docs/using-tcp-forwarding). 5 | 6 | This module will: 7 | 8 | - Create firewall rules to allow connections from IAP's TCP forwarding IP addresses to the TCP port 9 | of your resource's admin service. 10 | - Create IAM bindings to allow IAP from specified members. 11 | 12 | ## Usage 13 | 14 | Basic usage of this module is as follows: 15 | 16 | ```hcl 17 | module "iap_tunneling" { 18 | source = "terraform-google-modules/bastion-host/google//modules/iap-tunneling" 19 | 20 | project = var.project 21 | network = var.network 22 | service_accounts = [var.service_account_email] 23 | 24 | instances = [{ 25 | name = var.vm1_name 26 | zone = var.vm1_zone 27 | }] 28 | 29 | members = [ 30 | "group:devs@example.com", 31 | "user:me@example.com", 32 | ] 33 | } 34 | ``` 35 | 36 | Once the firewall rule is created, you can search for the newly created firewall rule with something 37 | similar to the following: 38 | 39 | ``` 40 | $ gcloud compute firewall-rules list --project my-project --filter="name=allow-ssh-from-iap-to-tunnel" 41 | NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED 42 | allow-ssh-from-iap-to-tunnel default INGRESS 1000 tcp:22 False 43 | ``` 44 | 45 | Once the IAM bindings for IAP-secured Tunnel User is created, you can verify them with something 46 | similar to the following: 47 | 48 | ``` 49 | $ curl -H "Authorization: Bearer $(gcloud auth print-access-token)" -X POST \ 50 | https://iap.googleapis.com/v1/projects/my-project/iap_tunnel/zones/us-central1-a/instances/my-instance:getIamPolicy 51 | { 52 | "bindings": [ 53 | { 54 | "role": "roles/iap.tunnelResourceAccessor", 55 | "members": [ 56 | "user:me@example.com" 57 | ] 58 | } 59 | ] 60 | } 61 | ``` 62 | 63 | ## Requirements 64 | 65 | These sections describe requirements for using this module. 66 | 67 | ### Software 68 | 69 | The following dependencies must be available: 70 | 71 | - [Terraform][terraform] v0.12 72 | - [Terraform Provider for GCP][terraform-provider-gcp] 73 | 74 | ### APIs 75 | 76 | A project with the following APIs enabled must be used to host the resources of this module: 77 | 78 | - Compute Engine API: `compute.googleapis.com` 79 | - Cloud Identity-Aware Proxy API: `iap.googleapis.com` 80 | 81 | The [Project Factory module][project-factory-module] can be used to provision a project with 82 | the necessary APIs enabled. 83 | 84 | 85 | ## Inputs 86 | 87 | | Name | Description | Type | Default | Required | 88 | |------|-------------|------|---------|:--------:| 89 | | additional\_ports | A list of additional ports/ranges to open access to on the instances from IAP. | `list(string)` | `[]` | no | 90 | | create\_firewall\_rule | If we need to create the firewall rule or not. | `bool` | `true` | no | 91 | | fw\_name\_allow\_ssh\_from\_iap | Firewall rule name for allowing SSH from IAP. | `string` | `"allow-ssh-from-iap-to-tunnel"` | no | 92 | | fw\_priority | Firewall rule priority for allowing SSH from IAP. | `number` | `null` | no | 93 | | host\_project | The network host project ID. | `string` | `""` | no | 94 | | instances | Names and zones of the instances to allow SSH from IAP. |
list(object({
name = string
zone = string
}))
| n/a | yes | 95 | | members | List of IAM resources to allow using the IAP tunnel. | `list(string)` | n/a | yes | 96 | | network | Self link of the network to attach the firewall to. | `string` | n/a | yes | 97 | | network\_tags | Network tags associated with the instances to allow SSH from IAP. Exactly one of service\_accounts or network\_tags should be specified. | `list(string)` | `[]` | no | 98 | | project | The project ID to deploy to. | `string` | n/a | yes | 99 | | service\_accounts | Service account emails associated with the instances to allow SSH from IAP. Exactly one of service\_accounts or network\_tags should be specified. | `list(string)` | `[]` | no | 100 | 101 | ## Outputs 102 | 103 | No outputs. 104 | 105 | 106 | 107 | ## Contributing 108 | 109 | Refer to the [contribution guidelines](./CONTRIBUTING.md) for 110 | information on contributing to this module. 111 | 112 | [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google 113 | [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html 114 | [terraform]: https://www.terraform.io/downloads.html 115 | -------------------------------------------------------------------------------- /modules/iap-tunneling/main.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 | resource "google_compute_firewall" "allow_from_iap_to_instances" { 18 | count = var.create_firewall_rule ? 1 : 0 19 | project = var.host_project != "" ? var.host_project : var.project 20 | name = var.fw_name_allow_ssh_from_iap 21 | network = var.network 22 | 23 | allow { 24 | protocol = "tcp" 25 | ports = toset(concat(["22"], var.additional_ports)) 26 | } 27 | 28 | # https://cloud.google.com/iap/docs/using-tcp-forwarding#before_you_begin 29 | # This is the netblock needed to forward to the instances 30 | source_ranges = ["35.235.240.0/20"] 31 | 32 | target_service_accounts = length(var.service_accounts) > 0 ? var.service_accounts : null 33 | target_tags = length(var.network_tags) > 0 ? var.network_tags : null 34 | priority = var.fw_priority 35 | } 36 | 37 | resource "google_iap_tunnel_instance_iam_binding" "enable_iap" { 38 | for_each = { 39 | for i in var.instances : 40 | "${i.name} ${i.zone}" => i 41 | } 42 | project = var.project 43 | zone = each.value.zone 44 | instance = each.value.name 45 | role = "roles/iap.tunnelResourceAccessor" 46 | members = var.members 47 | } 48 | -------------------------------------------------------------------------------- /modules/iap-tunneling/metadata.yaml: -------------------------------------------------------------------------------- 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 | apiVersion: blueprints.cloud.google.com/v1alpha1 16 | kind: BlueprintMetadata 17 | metadata: 18 | name: terraform-google-bastion-host 19 | annotations: 20 | config.kubernetes.io/local-config: "true" 21 | spec: 22 | title: iap-tunneling 23 | source: 24 | repo: https://github.com/terraform-google-modules/terraform-google-bastion-host 25 | sourceType: git 26 | version: 8.0.0 27 | actuationTool: 28 | type: Terraform 29 | version: '>=0.13' 30 | examples: 31 | - name: bastion_group 32 | location: examples/bastion_group 33 | - name: iap_tunneling 34 | location: examples/iap_tunneling 35 | - name: simple_example 36 | location: examples/simple_example 37 | - name: two_service_example 38 | location: examples/two_service_example 39 | variables: 40 | - name: additional_ports 41 | description: A list of additional ports/ranges to open access to on the instances from IAP. 42 | type: list(string) 43 | default: [] 44 | required: false 45 | - name: create_firewall_rule 46 | description: If we need to create the firewall rule or not. 47 | type: bool 48 | default: true 49 | required: false 50 | - name: fw_name_allow_ssh_from_iap 51 | description: Firewall rule name for allowing SSH from IAP. 52 | type: string 53 | default: allow-ssh-from-iap-to-tunnel 54 | required: false 55 | - name: host_project 56 | description: The network host project ID. 57 | type: string 58 | default: "" 59 | required: false 60 | - name: instances 61 | description: Names and zones of the instances to allow SSH from IAP. 62 | type: |- 63 | list(object({ 64 | name = string 65 | zone = string 66 | })) 67 | required: true 68 | - name: members 69 | description: List of IAM resources to allow using the IAP tunnel. 70 | type: list(string) 71 | required: true 72 | - name: network 73 | description: Self link of the network to attach the firewall to. 74 | type: string 75 | required: true 76 | - name: network_tags 77 | description: Network tags associated with the instances to allow SSH from IAP. Exactly one of service_accounts or network_tags should be specified. 78 | type: list(string) 79 | default: [] 80 | required: false 81 | - name: project 82 | description: The project ID to deploy to. 83 | type: string 84 | required: true 85 | - name: service_accounts 86 | description: Service account emails associated with the instances to allow SSH from IAP. Exactly one of service_accounts or network_tags should be specified. 87 | type: list(string) 88 | default: [] 89 | required: false 90 | roles: 91 | - level: Project 92 | roles: 93 | - roles/owner 94 | - roles/compute.admin 95 | - roles/compute.networkAdmin 96 | - roles/iam.serviceAccountUser 97 | - roles/compute.instanceAdmin 98 | - roles/compute.osLogin 99 | services: 100 | - cloudresourcemanager.googleapis.com 101 | - serviceusage.googleapis.com 102 | - compute.googleapis.com 103 | - iam.googleapis.com 104 | - oslogin.googleapis.com 105 | - iap.googleapis.com 106 | -------------------------------------------------------------------------------- /modules/iap-tunneling/variables.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 | variable "host_project" { 18 | description = "The network host project ID." 19 | type = string 20 | default = "" 21 | } 22 | 23 | variable "project" { 24 | description = "The project ID to deploy to." 25 | type = string 26 | } 27 | 28 | variable "fw_name_allow_ssh_from_iap" { 29 | description = "Firewall rule name for allowing SSH from IAP." 30 | type = string 31 | default = "allow-ssh-from-iap-to-tunnel" 32 | } 33 | 34 | variable "fw_priority" { 35 | description = "Firewall rule priority for allowing SSH from IAP." 36 | type = number 37 | default = null 38 | } 39 | 40 | variable "network" { 41 | description = "Self link of the network to attach the firewall to." 42 | type = string 43 | } 44 | 45 | variable "service_accounts" { 46 | description = "Service account emails associated with the instances to allow SSH from IAP. Exactly one of service_accounts or network_tags should be specified." 47 | type = list(string) 48 | default = [] 49 | } 50 | 51 | variable "network_tags" { 52 | description = "Network tags associated with the instances to allow SSH from IAP. Exactly one of service_accounts or network_tags should be specified." 53 | type = list(string) 54 | default = [] 55 | } 56 | 57 | variable "instances" { 58 | type = list(object({ 59 | name = string 60 | zone = string 61 | })) 62 | description = "Names and zones of the instances to allow SSH from IAP." 63 | } 64 | 65 | variable "members" { 66 | description = "List of IAM resources to allow using the IAP tunnel." 67 | type = list(string) 68 | } 69 | 70 | variable "additional_ports" { 71 | description = "A list of additional ports/ranges to open access to on the instances from IAP." 72 | type = list(string) 73 | default = [] 74 | } 75 | 76 | variable "create_firewall_rule" { 77 | type = bool 78 | description = "If we need to create the firewall rule or not." 79 | default = true 80 | } 81 | -------------------------------------------------------------------------------- /modules/iap-tunneling/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 | terraform { 17 | required_version = ">=0.13" 18 | required_providers { 19 | google = { 20 | source = "hashicorp/google" 21 | version = ">= 3.53, < 7" 22 | } 23 | } 24 | provider_meta "google" { 25 | module_name = "blueprints/terraform/terraform-google-bastion-host:iap-tunneling/v8.0.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /outputs.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 | output "service_account" { 17 | description = "The email for the service account created for the bastion host" 18 | value = local.service_account_email 19 | } 20 | 21 | output "hostname" { 22 | description = "Host name of the bastion" 23 | value = var.name 24 | } 25 | 26 | output "ip_address" { 27 | description = "Internal IP address of the bastion host" 28 | value = try((var.create_instance_from_template ? google_compute_instance_from_template.bastion_vm[0].network_interface[0].network_ip : ""), "") 29 | } 30 | 31 | output "self_link" { 32 | description = "Self link of the bastion host" 33 | value = try((var.create_instance_from_template ? google_compute_instance_from_template.bastion_vm[0].self_link : ""), "") 34 | } 35 | 36 | output "instance_template" { 37 | description = "Self link of the bastion instance template for use with a MIG" 38 | value = module.instance_template.self_link 39 | } 40 | -------------------------------------------------------------------------------- /test/integration/bastion_group/bastion_group_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 bastion_group 16 | 17 | import ( 18 | "fmt" 19 | "testing" 20 | 21 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" 22 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 23 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestBastionGroup(t *testing.T) { 28 | bpt := tft.NewTFBlueprintTest(t) 29 | 30 | bpt.DefineVerify(func(assert *assert.Assertions) { 31 | bpt.DefaultVerify(assert) 32 | 33 | projectId := bpt.GetStringOutput("project_id") 34 | 35 | ig := gcloud.Runf(t, "compute instance-groups list-instances bastion-mig --region us-west1 --project %s", projectId).Array() 36 | for _, instance := range ig { 37 | assert.Equal("RUNNING", instance.Get("status").String(), "is running") 38 | instanceData := gcloud.Runf(t, "compute instances describe %s --project %s", instance.Get("instance").String(), projectId) 39 | osLogin := utils.GetFirstMatchResult(t, instanceData.Get("metadata.items").Array(), "key", "enable-oslogin") 40 | assert.Equal("TRUE", osLogin.Get("value").String(), "os-login is enabled") 41 | for _, shieldedInstanceConfigValue := range instanceData.Get("shieldedInstanceConfig").Map() { 42 | assert.True(shieldedInstanceConfigValue.Bool(), "should have Shielded VM enabled") 43 | } 44 | } 45 | 46 | fw := gcloud.Runf(t, "compute firewall-rules describe allow-ssh-from-iap-to-bastion-group --project %s", projectId) 47 | assert.Equal("35.235.240.0/20", fw.Get("sourceRanges").Array()[0].String(), "has expected sourceRanges") 48 | assert.Equal("INGRESS", fw.Get("direction").String(), "has expected direction") 49 | assert.Equal(fmt.Sprintf("bastion-group@%s.iam.gserviceaccount.com", projectId), fw.Get("targetServiceAccounts").Array()[0].String(), "has correct target sa") 50 | assert.Equal("22", fw.Get("allowed").Array()[0].Map()["ports"].Array()[0].String(), "has expected allowed sports") 51 | }) 52 | 53 | bpt.Test() 54 | } 55 | -------------------------------------------------------------------------------- /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-bastion-host/test/integration 2 | 3 | go 1.22.7 4 | 5 | toolchain go1.22.9 6 | 7 | require ( 8 | github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.16.3 9 | github.com/stretchr/testify v1.10.0 10 | ) 11 | 12 | require ( 13 | cloud.google.com/go v0.110.7 // indirect 14 | cloud.google.com/go/compute v1.23.0 // indirect 15 | cloud.google.com/go/compute/metadata v0.2.3 // indirect 16 | cloud.google.com/go/iam v1.1.2 // indirect 17 | cloud.google.com/go/storage v1.33.0 // indirect 18 | github.com/agext/levenshtein v1.2.3 // indirect 19 | github.com/alexflint/go-filemutex v1.3.0 // indirect 20 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 21 | github.com/aws/aws-sdk-go v1.45.5 // indirect 22 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 23 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 24 | github.com/go-errors/errors v1.5.0 // indirect 25 | github.com/go-openapi/jsonpointer v0.20.0 // indirect 26 | github.com/go-openapi/jsonreference v0.20.2 // indirect 27 | github.com/go-openapi/swag v0.22.4 // indirect 28 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 29 | github.com/golang/protobuf v1.5.3 // indirect 30 | github.com/google/gnostic-models v0.6.8 // indirect 31 | github.com/google/go-cmp v0.6.0 // indirect 32 | github.com/google/s2a-go v0.1.7 // indirect 33 | github.com/google/uuid v1.6.0 // indirect 34 | github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect 35 | github.com/googleapis/gax-go/v2 v2.12.0 // indirect 36 | github.com/gruntwork-io/terratest v0.47.2 // 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-multierror v1.1.1 // indirect 41 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 42 | github.com/hashicorp/go-version v1.7.0 // indirect 43 | github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f // indirect 44 | github.com/hashicorp/hcl/v2 v2.20.1 // indirect 45 | github.com/hashicorp/terraform-config-inspect v0.0.0-20240801114854-6714b46f5fe4 // indirect 46 | github.com/hashicorp/terraform-json v0.23.0 // indirect 47 | github.com/jinzhu/copier v0.4.0 // indirect 48 | github.com/jmespath/go-jmespath v0.4.0 // indirect 49 | github.com/josharian/intern v1.0.0 // indirect 50 | github.com/klauspost/compress v1.16.7 // indirect 51 | github.com/mailru/easyjson v0.7.7 // indirect 52 | github.com/mattn/go-zglob v0.0.4 // indirect 53 | github.com/mitchellh/go-homedir v1.1.0 // indirect 54 | github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 // indirect 55 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 56 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 57 | github.com/tidwall/gjson v1.18.0 // indirect 58 | github.com/tidwall/match v1.1.1 // indirect 59 | github.com/tidwall/pretty v1.2.1 // indirect 60 | github.com/tidwall/sjson v1.2.5 // indirect 61 | github.com/tmccombs/hcl2json v0.6.0 // indirect 62 | github.com/ulikunitz/xz v0.5.11 // indirect 63 | github.com/zclconf/go-cty v1.15.0 // indirect 64 | go.opencensus.io v0.24.0 // indirect 65 | golang.org/x/crypto v0.21.0 // indirect 66 | golang.org/x/mod v0.21.0 // indirect 67 | golang.org/x/net v0.23.0 // indirect 68 | golang.org/x/oauth2 v0.12.0 // indirect 69 | golang.org/x/sync v0.4.0 // indirect 70 | golang.org/x/sys v0.21.0 // indirect 71 | golang.org/x/text v0.14.0 // indirect 72 | golang.org/x/tools v0.13.0 // indirect 73 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect 74 | google.golang.org/api v0.138.0 // indirect 75 | google.golang.org/appengine v1.6.8 // indirect 76 | google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect 77 | google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect 78 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect 79 | google.golang.org/grpc v1.58.3 // indirect 80 | google.golang.org/protobuf v1.33.0 // indirect 81 | gopkg.in/yaml.v3 v3.0.1 // indirect 82 | k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect 83 | sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect 84 | sigs.k8s.io/yaml v1.4.0 // indirect 85 | ) 86 | -------------------------------------------------------------------------------- /test/integration/iap_tunneling/iap_tunneling_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 iap_tunneling 16 | 17 | import ( 18 | "fmt" 19 | "testing" 20 | 21 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" 22 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 23 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestIapTunneling(t *testing.T) { 28 | bpt := tft.NewTFBlueprintTest(t) 29 | 30 | bpt.DefineVerify(func(assert *assert.Assertions) { 31 | bpt.DefaultVerify(assert) 32 | 33 | projectId := bpt.GetStringOutput("project_id") 34 | 35 | instance := gcloud.Runf(t, "compute instances describe iap-test-instance --zone us-west1-a --project %s", projectId) 36 | assert.Equal("RUNNING", instance.Get("status").String(), "is running") 37 | osLogin := utils.GetFirstMatchResult(t, instance.Get("metadata.items").Array(), "key", "enable-oslogin") 38 | assert.Equal("TRUE", osLogin.Get("value").String(), "os-login is enabled") 39 | 40 | fw := gcloud.Runf(t, "compute firewall-rules describe allow-ssh-from-iap-to-tunnel --project %s", projectId) 41 | assert.Equal("35.235.240.0/20", fw.Get("sourceRanges").Array()[0].String(), "has expected sourceRanges") 42 | assert.Equal("INGRESS", fw.Get("direction").String(), "has expected direction") 43 | assert.Equal(fmt.Sprintf("bastion@%s.iam.gserviceaccount.com", projectId), fw.Get("targetServiceAccounts").Array()[0].String(), "has correct target sa") 44 | assert.Equal("22", fw.Get("allowed").Array()[0].Map()["ports"].Array()[0].String(), "has expected allowed sports") 45 | }) 46 | 47 | bpt.Test() 48 | } 49 | -------------------------------------------------------------------------------- /test/integration/simple_example/simple_example_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 bastion_simple 16 | 17 | import ( 18 | "fmt" 19 | "testing" 20 | 21 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" 22 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 23 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestSimpleExample(t *testing.T) { 28 | bpt := tft.NewTFBlueprintTest(t) 29 | 30 | bpt.DefineVerify(func(assert *assert.Assertions) { 31 | bpt.DefaultVerify(assert) 32 | 33 | projectId := bpt.GetStringOutput("project_id") 34 | 35 | instance := gcloud.Runf(t, "compute instances describe bastion-vm --zone us-west1-a --project %s", projectId) 36 | assert.Equal("RUNNING", instance.Get("status").String(), "is running") 37 | osLogin := utils.GetFirstMatchResult(t, instance.Get("metadata.items").Array(), "key", "enable-oslogin") 38 | assert.Equal("TRUE", osLogin.Get("value").String(), "os-login is enabled") 39 | for _, shieldedInstanceConfigValue := range instance.Get("shieldedInstanceConfig").Map() { 40 | assert.True(shieldedInstanceConfigValue.Bool(), "should have Shielded VM enabled") 41 | } 42 | 43 | fw := gcloud.Runf(t, "compute firewall-rules describe allow-ssh-from-iap-to-tunnel --project %s", projectId) 44 | assert.Equal("35.235.240.0/20", fw.Get("sourceRanges").Array()[0].String(), "has expected sourceRanges") 45 | assert.Equal("INGRESS", fw.Get("direction").String(), "has expected direction") 46 | assert.Equal(fmt.Sprintf("bastion@%s.iam.gserviceaccount.com", projectId), fw.Get("targetServiceAccounts").Array()[0].String(), "has correct target sa") 47 | assert.Equal("22", fw.Get("allowed").Array()[0].Map()["ports"].Array()[0].String(), "has expected allowed sports") 48 | }) 49 | 50 | bpt.Test() 51 | } 52 | -------------------------------------------------------------------------------- /test/setup/.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfvars 2 | source.sh 3 | -------------------------------------------------------------------------------- /test/setup/iam.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 | locals { 18 | required_roles = [ 19 | "roles/owner", 20 | "roles/compute.admin", 21 | "roles/compute.networkAdmin", 22 | "roles/iam.serviceAccountUser", 23 | "roles/compute.instanceAdmin", 24 | "roles/compute.osLogin", 25 | ] 26 | } 27 | 28 | resource "google_service_account" "ci_account" { 29 | project = module.project_ci.project_id 30 | account_id = "ci-account" 31 | display_name = "ci-account" 32 | } 33 | 34 | resource "google_project_iam_member" "ci_account" { 35 | for_each = toset(local.required_roles) 36 | 37 | project = module.project_ci.project_id 38 | role = each.key 39 | member = "serviceAccount:${google_service_account.ci_account.email}" 40 | } 41 | 42 | resource "google_service_account_key" "ci_account" { 43 | service_account_id = google_service_account.ci_account.id 44 | } 45 | -------------------------------------------------------------------------------- /test/setup/main.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 | module "project_ci" { 18 | source = "terraform-google-modules/project-factory/google" 19 | version = "~> 17.0" 20 | name = "ci-bastion-module" 21 | random_project_id = true 22 | org_id = var.org_id 23 | folder_id = var.folder_id 24 | billing_account = var.billing_account 25 | 26 | activate_apis = [ 27 | "cloudresourcemanager.googleapis.com", 28 | "serviceusage.googleapis.com", 29 | "compute.googleapis.com", 30 | "iam.googleapis.com", 31 | "oslogin.googleapis.com", 32 | "iap.googleapis.com", 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /test/setup/outputs.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 | output "project_id" { 18 | value = module.project_ci.project_id 19 | } 20 | 21 | output "service_account_email" { 22 | value = google_service_account.ci_account.email 23 | } 24 | 25 | output "sa_key" { 26 | value = google_service_account_key.ci_account.private_key 27 | sensitive = true 28 | } 29 | 30 | output "members" { 31 | value = ["serviceAccount:${google_service_account.ci_account.email}"] 32 | } 33 | -------------------------------------------------------------------------------- /test/setup/variables.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 | 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 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 = ">= 0.13" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /variables.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 | variable "image" { 18 | type = string 19 | 20 | description = "Source image for the Bastion. If image is not specified, image_family will be used (which is the default)." 21 | default = "" 22 | } 23 | 24 | variable "image_family" { 25 | type = string 26 | 27 | description = "Source image family for the Bastion." 28 | default = "debian-12" 29 | } 30 | 31 | variable "image_project" { 32 | type = string 33 | 34 | description = "Project where the source image for the Bastion comes from" 35 | default = "debian-cloud" 36 | } 37 | 38 | variable "create_instance_from_template" { 39 | type = bool 40 | 41 | description = "Whether to create and instance from the template or not. If false, no instance is created, but the instance template is created and usable by a MIG" 42 | default = true 43 | } 44 | 45 | variable "tags" { 46 | type = list(string) 47 | 48 | description = "Network tags, provided as a list" 49 | default = [] 50 | } 51 | 52 | variable "labels" { 53 | type = map(any) 54 | 55 | description = "Key-value map of labels to assign to the bastion host" 56 | default = {} 57 | } 58 | 59 | variable "machine_type" { 60 | type = string 61 | description = "Instance type for the Bastion host" 62 | default = "n1-standard-1" 63 | } 64 | 65 | variable "members" { 66 | type = list(string) 67 | 68 | description = "List of IAM resources to allow access to the bastion host" 69 | default = [] 70 | } 71 | 72 | variable "name" { 73 | type = string 74 | 75 | description = "Name of the Bastion instance" 76 | default = "bastion-vm" 77 | } 78 | 79 | variable "name_prefix" { 80 | type = string 81 | 82 | description = "Name prefix for instance template" 83 | default = "bastion-instance-template" 84 | } 85 | variable "network" { 86 | type = string 87 | 88 | description = "Self link for the network on which the Bastion should live" 89 | } 90 | 91 | variable "network_ip" { 92 | type = string 93 | description = "Private IP address for the bastion host" 94 | default = "" 95 | } 96 | 97 | variable "project" { 98 | type = string 99 | 100 | description = "The project ID to deploy to" 101 | } 102 | 103 | variable "host_project" { 104 | type = string 105 | 106 | description = "The network host project ID" 107 | default = "" 108 | } 109 | 110 | variable "scopes" { 111 | type = list(string) 112 | 113 | description = "List of scopes to attach to the bastion host" 114 | default = ["cloud-platform"] 115 | } 116 | 117 | variable "service_account_roles" { 118 | type = list(string) 119 | 120 | description = "List of IAM roles to assign to the service account." 121 | default = [ 122 | "roles/logging.logWriter", 123 | "roles/monitoring.metricWriter", 124 | "roles/monitoring.viewer", 125 | "roles/compute.osLogin", 126 | ] 127 | } 128 | 129 | variable "service_account_roles_supplemental" { 130 | type = list(string) 131 | description = "An additional list of roles to assign to the bastion if desired" 132 | default = [] 133 | } 134 | 135 | variable "service_account_name" { 136 | type = string 137 | 138 | description = "Account ID for the service account" 139 | default = "bastion" 140 | } 141 | 142 | variable "service_account_email" { 143 | type = string 144 | 145 | description = "If set, the service account and its permissions will not be created. The service account being passed in should have at least the roles listed in the `service_account_roles` variable so that logging and OS Login work as expected." 146 | default = "" 147 | } 148 | 149 | variable "shielded_vm" { 150 | type = bool 151 | 152 | description = "Enable shielded VM on the bastion host (recommended)" 153 | default = true 154 | } 155 | 156 | variable "startup_script" { 157 | type = string 158 | 159 | description = "Render a startup script with a template." 160 | default = "" 161 | } 162 | 163 | variable "subnet" { 164 | type = string 165 | 166 | description = "Self link for the subnet on which the Bastion should live. Can be private when using IAP" 167 | } 168 | 169 | variable "zone" { 170 | type = string 171 | 172 | description = "The primary zone where the bastion host will live" 173 | default = "us-central1-a" 174 | } 175 | 176 | variable "region" { 177 | type = string 178 | 179 | description = "The region where the bastion instance template will live" 180 | default = null 181 | } 182 | 183 | variable "random_role_id" { 184 | type = bool 185 | 186 | description = "Enables role random id generation." 187 | default = true 188 | } 189 | 190 | variable "fw_name_allow_ssh_from_iap" { 191 | type = string 192 | 193 | description = "Firewall rule name for allowing SSH from IAP" 194 | default = "allow-ssh-from-iap-to-tunnel" 195 | } 196 | 197 | variable "additional_ports" { 198 | description = "A list of additional ports/ranges to open access to on the instances from IAP." 199 | type = list(string) 200 | default = [] 201 | } 202 | 203 | variable "disk_size_gb" { 204 | description = "Boot disk size in GB" 205 | type = number 206 | default = 100 207 | } 208 | 209 | variable "disk_type" { 210 | description = "Boot disk type, can be either pd-ssd, local-ssd, or pd-standard" 211 | type = string 212 | default = "pd-standard" 213 | } 214 | 215 | variable "disk_labels" { 216 | type = map(any) 217 | 218 | description = "Key-value map of labels to assign to the bastion host disk" 219 | default = {} 220 | } 221 | 222 | variable "metadata" { 223 | type = map(string) 224 | description = "Key-value map of additional metadata to assign to the instances" 225 | default = {} 226 | } 227 | 228 | variable "external_ip" { 229 | type = bool 230 | description = "Set to true if an ephemeral or static external IP/DNS is required, must also set access_config if true" 231 | default = false 232 | } 233 | 234 | variable "preemptible" { 235 | type = bool 236 | description = "Allow the instance to be preempted" 237 | default = false 238 | } 239 | 240 | variable "access_config" { 241 | description = "Access configs for network, nat_ip and DNS" 242 | type = list(object({ 243 | network_tier = string 244 | nat_ip = string 245 | public_ptr_domain_name = string 246 | })) 247 | default = [{ 248 | nat_ip = "", 249 | network_tier = "PREMIUM", 250 | public_ptr_domain_name = "" 251 | }] 252 | } 253 | 254 | variable "create_firewall_rule" { 255 | type = bool 256 | description = "If we need to create the firewall rule or not." 257 | default = true 258 | } 259 | 260 | variable "additional_networks" { 261 | description = "Additional network interface details for the instance template, if any." 262 | default = [] 263 | type = list(object({ 264 | network = string 265 | subnetwork = string 266 | subnetwork_project = string 267 | network_ip = string 268 | nic_type = string 269 | stack_type = string 270 | queue_count = number 271 | access_config = list(object({ 272 | nat_ip = string 273 | network_tier = string 274 | })) 275 | ipv6_access_config = list(object({ 276 | network_tier = string 277 | })) 278 | alias_ip_range = list(object({ 279 | ip_cidr_range = string 280 | subnetwork_range_name = string 281 | })) 282 | })) 283 | } 284 | 285 | variable "can_ip_forward" { 286 | type = bool 287 | description = "Whether the bastion should allow IP forwarding." 288 | default = false 289 | } 290 | -------------------------------------------------------------------------------- /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 | terraform { 17 | required_version = ">=0.13" 18 | required_providers { 19 | google = { 20 | source = "hashicorp/google" 21 | version = ">= 3.53, < 7" 22 | } 23 | random = { 24 | source = "hashicorp/random" 25 | version = ">= 3.0" 26 | } 27 | } 28 | provider_meta "google" { 29 | module_name = "blueprints/terraform/terraform-google-bastion-host/v8.0.0" 30 | } 31 | } 32 | --------------------------------------------------------------------------------