diff --git a/modules/secret-manager/README.md b/modules/secret-manager/README.md index 601abc35b..b1617e621 100644 --- a/modules/secret-manager/README.md +++ b/modules/secret-manager/README.md @@ -35,7 +35,7 @@ module "secret-manager" { test-auto = null test-manual = ["europe-west1", "europe-west4"] } - iam_members = { + iam = { test-auto = { "roles/secretmanager.secretAccessor" = ["group:auto-readers@example.com"] } @@ -76,7 +76,7 @@ module "secret-manager" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| | project_id | Project id where the keyring will be created. | string | ✓ | | -| *iam_members* | IAM members keyed by secret name and role. | map(map(set(string))) | | {} | +| *iam* | IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} | | *labels* | Optional labels for each secret. | map(map(string)) | | {} | | *secrets* | Map of secrets to manage and their locations. If locations is null, automatic management will be set. | map(list(string)) | | {} | | *versions* | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | map(map(object({...}))) | | {} | diff --git a/modules/secret-manager/main.tf b/modules/secret-manager/main.tf index db52b12b1..741797805 100644 --- a/modules/secret-manager/main.tf +++ b/modules/secret-manager/main.tf @@ -16,8 +16,8 @@ locals { # distinct is needed to make the expanding function argument work - iam_members = flatten([ - for secret, roles in var.iam_members : [ + iam = flatten([ + for secret, roles in var.iam : [ for role, members in roles : { secret = secret role = role @@ -77,8 +77,7 @@ resource "google_secret_manager_secret_version" "default" { resource "google_secret_manager_secret_iam_binding" "default" { provider = google-beta for_each = { - for binding in local.iam_members : - "${binding.secret}.${binding.role}" => binding + for binding in local.iam : "${binding.secret}.${binding.role}" => binding } role = each.value.role secret_id = google_secret_manager_secret.default[each.value.secret].id diff --git a/modules/secret-manager/variables.tf b/modules/secret-manager/variables.tf index 1517fea40..0b8afef96 100644 --- a/modules/secret-manager/variables.tf +++ b/modules/secret-manager/variables.tf @@ -14,9 +14,9 @@ * limitations under the License. */ -variable "iam_members" { - description = "IAM members keyed by secret name and role." - type = map(map(set(string))) +variable "iam" { + description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format." + type = map(map(list(string))) default = {} } diff --git a/tests/modules/secret_manager/__init__.py b/tests/modules/secret_manager/__init__.py new file mode 100644 index 000000000..6913f02e3 --- /dev/null +++ b/tests/modules/secret_manager/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/modules/secret_manager/fixture/main.tf b/tests/modules/secret_manager/fixture/main.tf new file mode 100644 index 000000000..42b431020 --- /dev/null +++ b/tests/modules/secret_manager/fixture/main.tf @@ -0,0 +1,42 @@ +/** + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module "test" { + source = "../../../../modules/secret-manager" + project_id = "my-project" + iam = { + secret-1 = { + "roles/secretmanager.secretAccessor" = [ + "serviceAccount:service-account.example.com" + ] + } + secret-2 = { + "roles/secretmanager.viewer" = [ + "serviceAccount:service-account.example.com" + ] + } + } + secrets = { + secret-1 = ["europe-west1"], + secret-2 = null + } + versions = { + secret-1 = { + foobar = { enabled = true, data = "foobar" } + } + } + labels = var.labels +} diff --git a/tests/modules/secret_manager/fixture/variables.tf b/tests/modules/secret_manager/fixture/variables.tf new file mode 100644 index 000000000..124606985 --- /dev/null +++ b/tests/modules/secret_manager/fixture/variables.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "labels" { + type = map(map(string)) + default = {} +} diff --git a/tests/modules/secret_manager/test_plan.py b/tests/modules/secret_manager/test_plan.py new file mode 100644 index 000000000..44f1f5db9 --- /dev/null +++ b/tests/modules/secret_manager/test_plan.py @@ -0,0 +1,41 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +import pytest + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') + + +@pytest.fixture +def resources(plan_runner): + _, resources = plan_runner(FIXTURES_DIR) + return resources + + +def test_resource_count(resources): + "Test number of resources created." + assert len(resources) == 5 + + +def test_secret_iam(resources): + "Test secret IAM binding resources." + bindings = [r['values'] for r in resources if r['type'] + == 'google_secret_manager_secret_iam_binding'] + assert len(bindings) == 2 + assert set(b['role'] for b in bindings) == set([ + 'roles/secretmanager.secretAccessor', 'roles/secretmanager.viewer' + ])