diff --git a/.kitchen.yml b/.kitchen.yml deleted file mode 100644 index 92086f8..0000000 --- a/.kitchen.yml +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2018 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. - ---- -driver: - name: terraform - -provisioner: - name: terraform - -verifier: - name: terraform - -platforms: - - name: default - -suites: - - name: single_service_account - driver: - root_module_directory: test/fixtures/single_service_account/ - verify_version: false - verifier: - color: false - systems: - - name: single_service_account gcp - backend: gcp - controls: - - gcp - - name: multiple_service_accounts - driver: - root_module_directory: test/fixtures/multiple_service_accounts/ - verify_version: false - verifier: - color: false - systems: - - name: multiple_service_accounts gcp - backend: gcp - controls: - - gcp - - name: key_distributor - driver: - root_module_directory: test/fixtures/key_distributor/ - verify_version: false - verifier: - color: false - systems: - - name: key_distributor - backend: local diff --git a/Makefile b/Makefile index b5dd4bd..097a594 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ docker_test_integration: -e SERVICE_ACCOUNT_JSON \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ - /usr/local/bin/test_integration.sh + cft test run all # Execute lint tests within the docker container .PHONY: docker_test_lint diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index dad8a11..dd65afe 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -24,26 +24,14 @@ steps: - 'TF_VAR_org_id=$_ORG_ID' - 'TF_VAR_folder_id=$_FOLDER_ID' - 'TF_VAR_billing_account=$_BILLING_ACCOUNT' -- id: create - name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' - args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do create'] -- id: create-all +- id: init-all waitFor: - prepare name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose'] -- id: converge - name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' - args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do converge'] -- id: verify - name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' - args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do verify'] -- id: destroy - name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' - args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do destroy'] - id: apply simple-sa waitFor: - - create-all + - init-all name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestSimpleSA --stage apply --verbose'] - id: verify simple-sa @@ -56,6 +44,21 @@ steps: - verify simple-sa name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestSimpleSA --stage teardown --verbose'] +- id: single-service-account + waitFor: + - init-all + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestSingleServiceAccount --verbose'] +- id: multiple-service-accounts + waitFor: + - init-all + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestMultipleServiceAccounts --verbose'] +- id: key-distributor + waitFor: + - init-all + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestKeyDistributor --verbose'] tags: - 'ci' - 'integration' diff --git a/examples/multiple_service_accounts/outputs.tf b/examples/multiple_service_accounts/outputs.tf index 0883011..14f64b3 100644 --- a/examples/multiple_service_accounts/outputs.tf +++ b/examples/multiple_service_accounts/outputs.tf @@ -32,5 +32,6 @@ output "iam_emails" { output "keys" { description = "The service account keys." value = module.service_accounts.keys + sensitive = true } diff --git a/test/fixtures/multiple_service_accounts/main.tf b/test/fixtures/multiple_service_accounts/main.tf deleted file mode 100644 index c20a3e1..0000000 --- a/test/fixtures/multiple_service_accounts/main.tf +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2018 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 "example" { - source = "../../../examples/multiple_service_accounts" - project_id = var.project_id -} - diff --git a/test/fixtures/multiple_service_accounts/outputs.tf b/test/fixtures/multiple_service_accounts/outputs.tf deleted file mode 100644 index 1434674..0000000 --- a/test/fixtures/multiple_service_accounts/outputs.tf +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright 2018 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. - */ - -output "emails" { - description = "The service account emails." - value = module.example.emails -} - -output "emails_list" { - description = "The service account emails as a list." - value = module.example.emails_list -} - -output "iam_emails" { - description = "The service account IAM-format emails as a map." - value = module.example.iam_emails -} - -output "keys" { - description = "The service account keys." - value = module.example.keys - sensitive = true -} - -output "project_id" { - description = "Project id variable." - value = var.project_id -} - diff --git a/test/fixtures/multiple_service_accounts/variables.tf b/test/fixtures/multiple_service_accounts/variables.tf deleted file mode 100644 index 1f95eaa..0000000 --- a/test/fixtures/multiple_service_accounts/variables.tf +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2018 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 "project_id" { - description = "The ID of the project in which to provision resources." - type = string -} - diff --git a/test/fixtures/multiple_service_accounts/versions.tf b/test/fixtures/multiple_service_accounts/versions.tf deleted file mode 100644 index 9b7f746..0000000 --- a/test/fixtures/multiple_service_accounts/versions.tf +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright 2019 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. - */ - -terraform { - required_version = ">= 1.3" -} diff --git a/test/fixtures/single_service_account/main.tf b/test/fixtures/single_service_account/main.tf deleted file mode 100644 index 74ec8f5..0000000 --- a/test/fixtures/single_service_account/main.tf +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2018 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 "example" { - source = "../../../examples/single_service_account" - project_id = var.project_id -} - diff --git a/test/fixtures/single_service_account/outputs.tf b/test/fixtures/single_service_account/outputs.tf deleted file mode 100644 index ab01cda..0000000 --- a/test/fixtures/single_service_account/outputs.tf +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2018 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. - */ - -output "email" { - description = "The service account email." - value = module.example.email -} - -output "iam_email" { - description = "The service account IAM-format email." - value = module.example.iam_email -} - -output "project_id" { - description = "Project id variable." - value = var.project_id -} - diff --git a/test/fixtures/single_service_account/variables.tf b/test/fixtures/single_service_account/variables.tf deleted file mode 100644 index 1f95eaa..0000000 --- a/test/fixtures/single_service_account/variables.tf +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2018 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 "project_id" { - description = "The ID of the project in which to provision resources." - type = string -} - diff --git a/test/fixtures/single_service_account/versions.tf b/test/fixtures/single_service_account/versions.tf deleted file mode 100644 index e09fed8..0000000 --- a/test/fixtures/single_service_account/versions.tf +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright 2018 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. - */ - -terraform { - required_version = ">= 1.3" -} diff --git a/test/integration/go.mod b/test/integration/go.mod index 63aa813..00a537e 100644 --- a/test/integration/go.mod +++ b/test/integration/go.mod @@ -7,6 +7,7 @@ toolchain go1.24.7 require ( github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9 github.com/stretchr/testify v1.11.1 + github.com/tidwall/gjson v1.18.0 ) require ( @@ -42,7 +43,6 @@ require ( github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect diff --git a/test/integration/key_distributor/controls/gcp.rb b/test/integration/key_distributor/controls/gcp.rb deleted file mode 100644 index 9756c12..0000000 --- a/test/integration/key_distributor/controls/gcp.rb +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2018 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 -# -# https://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. -require "base64" -require "json" - -control "key_distributor" do - title "GCP Resources" - describe command("./test/fixtures/key_distributor/get-key #{attribute('email')}") do - its(:exit_status) { should eq 0 } - its(:stderr) { should eq '' } - its(:stdout) do - should start_with("Success! Wrote encrypted key") - end - end - -end diff --git a/test/integration/key_distributor/inspec.yml b/test/integration/key_distributor/inspec.yml deleted file mode 100644 index 29e8511..0000000 --- a/test/integration/key_distributor/inspec.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2021 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. - -name: key_distributor -attributes: - - name: email - required: true - type: string diff --git a/test/integration/key_distributor/key_distributor_test.go b/test/integration/key_distributor/key_distributor_test.go new file mode 100644 index 0000000..f91b0ff --- /dev/null +++ b/test/integration/key_distributor/key_distributor_test.go @@ -0,0 +1,46 @@ +// Copyright 2025 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. + +package key_distributor_test + +import ( + "os/exec" + "strings" + "testing" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestKeyDistributor(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t) + bpt.DefineVerify( + func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + email := bpt.GetStringOutput("email") + + cmd := exec.Command("./../../fixtures/key_distributor/get-key", email) + var stdout strings.Builder + var stderr strings.Builder + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + assert.Nil(cmd.Run()) + + assert.Equal("", stderr.String()) + assert.Regexp("^Success! Wrote encrypted key", stdout.String()) + }) + bpt.Test() +} diff --git a/test/integration/multiple_service_accounts/controls/gcp.rb b/test/integration/multiple_service_accounts/controls/gcp.rb deleted file mode 100644 index 4272287..0000000 --- a/test/integration/multiple_service_accounts/controls/gcp.rb +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2018 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 -# -# https://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. - -control "gcp" do - title "GCP Resources" - - attribute('iam_emails').each_value do |email| - describe google_project_iam_binding(project: "#{attribute("project_id")}", role: 'roles/viewer') do - its('members') {should include email } - end - describe google_project_iam_binding(project: "#{attribute("project_id")}", role: 'roles/storage.objectViewer') do - its('members') {should include email } - end - end - - attribute('emails_list').each do |email| - describe google_service_accounts(project: "#{attribute('project_id')}") do - its('service_account_emails'){ should include email } - end - end - -end diff --git a/test/integration/multiple_service_accounts/inspec.yml b/test/integration/multiple_service_accounts/inspec.yml deleted file mode 100644 index dfa7304..0000000 --- a/test/integration/multiple_service_accounts/inspec.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2021 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. - -name: multiple_service_accounts -depends: - - name: inspec-gcp - git: https://github.com/inspec/inspec-gcp.git - tag: v1.8.0 -attributes: - - name: project_id - required: true - type: string - - name: emails - required: true - type: hash - - name: emails_list - required: true - type: array - - name: iam_emails - required: true - type: hash diff --git a/test/integration/multiple_service_accounts/multiple_service_accounts_test.go b/test/integration/multiple_service_accounts/multiple_service_accounts_test.go new file mode 100644 index 0000000..c7764ab --- /dev/null +++ b/test/integration/multiple_service_accounts/multiple_service_accounts_test.go @@ -0,0 +1,82 @@ +// Copyright 2025 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. + +package multiple_service_accounts + +import ( + "fmt" + "testing" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" + "github.com/tidwall/gjson" +) + +// membersOfRole queries the given project using gcloud for the members +// of the given role. The result is returned as a plain []string. +func membersOfRole(t *testing.T, projectID string, role string) ([]string, error) { + cmd := fmt.Sprintf("projects get-iam-policy %s --flatten=bindings --filter=bindings.role:'%s' --format=json", projectID, role) + output, err := gcloud.RunCmdE(t, cmd) + if err != nil { + return nil, fmt.Errorf("Failed running %q: %v, output=%q", cmd, err, output) + } + + bindings := gjson.Parse(output).Array() + if len(bindings) != 1 { + return nil, fmt.Errorf("filtering for one role should produce one binding, instead got %v", output) + } + + var members []string + for _, member := range bindings[0].Get("bindings.members").Array() { + members = append(members, member.String()) + } + return members, nil +} + +func TestMultipleServiceAccounts(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t) + bpt.DefineVerify( + func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + project_id := bpt.GetTFSetupStringOutput("project_id") + + viewers, err := membersOfRole(t, project_id, "roles/viewer") + assert.Nil(err) + objectViewers, err := membersOfRole(t, project_id, "roles/storage.objectViewer") + assert.Nil(err) + + iam_emails := bpt.GetJsonOutput("iam_emails").Map() + assert.Len(iam_emails, 2, "expected 2 entries in output iam_emails") + + for _, email := range iam_emails { + assert.Contains(viewers, email.String(), "expected to find %q in queried viewers list", email.String()) + assert.Contains(objectViewers, email.String(), "expected to find %q in queried storage.objectViewers list", email.String()) + } + + foundEmailsJSON := gcloud.Runf(t, "iam service-accounts list --project=%s --flatten=email", project_id).Array() + var foundEmails []string + for _, found := range foundEmailsJSON { + foundEmails = append(foundEmails, found.String()) + } + + emails_list := bpt.GetJsonOutput("emails_list").Array() + assert.Len(emails_list, 2, "expected 2 entries in output emails_list") + for _, email := range emails_list { + assert.Contains(foundEmails, email.String(), "expected to find %q in queried emails list", email.String()) + } + }) + bpt.Test() +} diff --git a/test/integration/single_service_account/controls/gcp.rb b/test/integration/single_service_account/controls/gcp.rb deleted file mode 100644 index 9463ae6..0000000 --- a/test/integration/single_service_account/controls/gcp.rb +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2018 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 -# -# https://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. - -control "gcp" do - title "GCP Resources" - - describe google_service_account(project: attribute("project_id"), name: attribute("email")) do - its('project_id') { should eq attribute('project_id') } - end - - describe google_project_iam_binding(project: "#{attribute("project_id")}", role: 'roles/viewer') do - its('members') {should include attribute('iam_email') } - end - -end diff --git a/test/integration/single_service_account/inspec.yml b/test/integration/single_service_account/inspec.yml deleted file mode 100644 index 7fd2f7a..0000000 --- a/test/integration/single_service_account/inspec.yml +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2021 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. - -name: single_service_account -depends: - - name: inspec-gcp - git: https://github.com/inspec/inspec-gcp.git - tag: v1.8.0 -attributes: - - name: project_id - required: true - type: string - - name: email - required: true - type: string - - name: iam_email - required: true - type: string diff --git a/test/integration/single_service_account/single_service_account_test.go b/test/integration/single_service_account/single_service_account_test.go new file mode 100644 index 0000000..8693133 --- /dev/null +++ b/test/integration/single_service_account/single_service_account_test.go @@ -0,0 +1,48 @@ +// Copyright 2025 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. + +package single_service_account + +import ( + "testing" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestSingleServiceAccount(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t) + bpt.DefineVerify( + func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + project_id := bpt.GetTFSetupStringOutput("project_id") + email := bpt.GetStringOutput("email") + iam_email := bpt.GetStringOutput("iam_email") + + assert.Equal(project_id, gcloud.Runf(t, "iam service-accounts describe %s --format=json", email).Get("projectId").String(), "fetched project ID should match") + + role := "roles/viewer" + bindings := gcloud.Runf(t, "projects get-iam-policy %s --flatten=bindings --filter=bindings.role:'%s' --format=json", project_id, role).Array() + assert.Len(bindings, 1, "filtering for one role should produce one binding, instead got %v", bindings) + + var viewers []string + for _, member := range bindings[0].Get("bindings.members").Array() { + viewers = append(viewers, member.String()) + } + assert.Contains(viewers, iam_email, "expected to find %q in queried viewers list", iam_email) + }) + bpt.Test() +}