diff --git a/ci/cloudbuild/builds/integration-daily.sh b/ci/cloudbuild/builds/integration-daily.sh index a56e6cfe82a58..e007ed7db1f29 100755 --- a/ci/cloudbuild/builds/integration-daily.sh +++ b/ci/cloudbuild/builds/integration-daily.sh @@ -48,11 +48,11 @@ integration::bazel_with_emulators test "${args[@]}" "${integration_args[@]}" io::log_h2 "Running Bigtable integration tests (against prod)" bazel test "${args[@]}" "${integration_args[@]}" \ - --test_tag_filters="integration-test" -- \ + --test_tag_filters="integration-test,-ud-only" -- \ "//google/cloud/bigtable/..." \ "-//google/cloud/bigtable/examples:bigtable_grpc_credentials" io::log_h2 "Running Spanner integration tests (against prod)" bazel test "${args[@]}" "${integration_args[@]}" \ - --test_tag_filters="integration-test" --test_timeout=-1,-1,-1,10800 \ + --test_tag_filters="integration-test,-ud-only" --test_timeout=-1,-1,-1,10800 \ "//google/cloud/spanner/..." diff --git a/ci/cloudbuild/builds/integration-production.sh b/ci/cloudbuild/builds/integration-production.sh index b487db626dee2..fb92d5665573c 100755 --- a/ci/cloudbuild/builds/integration-production.sh +++ b/ci/cloudbuild/builds/integration-production.sh @@ -40,5 +40,5 @@ excluded_rules=( io::log_h2 "Running the integration tests against prod" mapfile -t integration_args < <(integration::bazel_args) io::run bazel test "${args[@]}" "${integration_args[@]}" \ - --cache_test_results="auto" --test_tag_filters="integration-test" \ + --cache_test_results="auto" --test_tag_filters="integration-test,-ud-only" \ -- "${BAZEL_TARGETS[@]}" "${excluded_rules[@]}" diff --git a/ci/cloudbuild/builds/lib/integration.sh b/ci/cloudbuild/builds/lib/integration.sh index b9399634db520..73da705584dff 100644 --- a/ci/cloudbuild/builds/lib/integration.sh +++ b/ci/cloudbuild/builds/lib/integration.sh @@ -178,30 +178,30 @@ function integration::bazel_with_emulators() { "google/cloud:internal_unified_rest_credentials_integration_test" ) - production_tests_tag_filters="integration-test" + production_tests_tag_filters="integration-test,-ud-only" if echo "${args[@]}" | grep -w -q -- "--config=msan"; then - production_tests_tag_filters="integration-test,-no-msan" + production_tests_tag_filters="integration-test,-no-msan,-ud-only" fi io::log_h2 "Running Pub/Sub integration tests (with emulator)" "google/cloud/pubsub/ci/${EMULATOR_SCRIPT}" \ - bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test" + bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test,-ud-only" io::log_h2 "Running Storage integration tests (with emulator)" "google/cloud/storage/ci/${EMULATOR_SCRIPT}" \ - bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test" + bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test,-ud-only" io::log_h2 "Running Spanner integration tests (with emulator)" "google/cloud/spanner/ci/${EMULATOR_SCRIPT}" \ - bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test" + bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test,-ud-only" io::log_h2 "Running Bigtable integration tests (with emulator)" "google/cloud/bigtable/ci/${EMULATOR_SCRIPT}" \ - bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test" + bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test,-ud-only" io::log_h2 "Running REST integration tests (with emulator)" "google/cloud/internal/ci/${EMULATOR_SCRIPT}" \ - bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test" + bazel "${verb}" "${args[@]}" --test_tag_filters="integration-test,-ud-only" if [[ "${BAZEL_TARGETS[*]}" != "..." ]]; then io::log_h2 "Skipping some integration tests because BAZEL_TARGETS is not the default" diff --git a/ci/cloudbuild/builds/lib/universe_domain.sh b/ci/cloudbuild/builds/lib/universe_domain.sh index 728c9a7bdb270..3ee0ec130f802 100644 --- a/ci/cloudbuild/builds/lib/universe_domain.sh +++ b/ci/cloudbuild/builds/lib/universe_domain.sh @@ -43,5 +43,7 @@ function ud::bazel_test() { bazel test "${args[@]}" --sandbox_add_mount_pair=/tmp \ --test_env=UD_SA_KEY_FILE="${UD_SA_KEY_FILE}" \ --test_env=UD_REGION="${UD_REGION}" \ + --test_env=UD_ZONE="${UD_ZONE}" \ + --test_env=UD_IMPERSONATED_SERVICE_ACCOUNT_NAME="${UD_IMPERSONATED_SERVICE_ACCOUNT_NAME}" \ --test_env=UD_PROJECT="${UD_PROJECT}" -- "$@" } diff --git a/ci/cloudbuild/builds/universe-domain-demo.sh b/ci/cloudbuild/builds/universe-domain-demo.sh index 02aace8d2f777..9877b3574cf0b 100755 --- a/ci/cloudbuild/builds/universe-domain-demo.sh +++ b/ci/cloudbuild/builds/universe-domain-demo.sh @@ -29,6 +29,7 @@ if [[ -n "${UD_SA_KEY_FILE}" ]]; then ud::bazel_run //google/cloud/universe_domain/demo:kms_demo \ "${UD_PROJECT}" "${UD_REGION}" "${UD_SA_KEY_FILE}" ud::bazel_test //google/cloud/storage/tests:universe_domain_integration_test + ud::bazel_test //google/cloud/universe_domain/integration_tests:impersonation_tests else source module ci/etc/integration-tests-config.sh bazel run -- //google/cloud/universe_domain/demo:kms_demo \ diff --git a/ci/cloudbuild/cloudbuild.yaml b/ci/cloudbuild/cloudbuild.yaml index 00c9acf5c90d3..db20831188f05 100644 --- a/ci/cloudbuild/cloudbuild.yaml +++ b/ci/cloudbuild/cloudbuild.yaml @@ -70,11 +70,14 @@ availableSecrets: env: 'UD_PROJECT' - versionName: 'projects/${PROJECT_ID}/secrets/UD_REGION/versions/latest' env: 'UD_REGION' + - versionName: 'projects/${PROJECT_ID}/secrets/UD_ZONE/versions/latest' + env: 'UD_ZONE' - versionName: 'projects/${PROJECT_ID}/secrets/UD_SERVICE_ACCOUNT/versions/latest' env: 'UD_SERVICE_ACCOUNT' - versionName: 'projects/${PROJECT_ID}/secrets/UD_SERVICE_ACCOUNT_NAME/versions/latest' env: 'UD_SERVICE_ACCOUNT_NAME' - + - versionName: 'projects/${PROJECT_ID}/secrets/UD_IMPERSONATED_SERVICE_ACCOUNT_NAME/versions/latest' + env: 'UD_IMPERSONATED_SERVICE_ACCOUNT_NAME' logsBucket: 'gs://${_LOGS_BUCKET}/logs/google-cloud-cpp/${_TRIGGER_SOURCE}/${COMMIT_SHA}/${_DISTRO}-${_BUILD_NAME}-${_SHARD}' @@ -112,7 +115,7 @@ steps: - name: '${_POOL_REGION}-docker.pkg.dev/${PROJECT_ID}/gcb/${_IMAGE}:${BUILD_ID}' entrypoint: 'ci/cloudbuild/build.sh' args: [ '--local', '--build', '${_BUILD_NAME}' ] - secretEnv: ['CODECOV_TOKEN', 'UD', 'UD_PROJECT', 'UD_REGION', 'UD_SERVICE_ACCOUNT', 'UD_SERVICE_ACCOUNT_NAME'] + secretEnv: ['CODECOV_TOKEN', 'UD', 'UD_PROJECT', 'UD_REGION', 'UD_ZONE', 'UD_SERVICE_ACCOUNT', 'UD_SERVICE_ACCOUNT_NAME', 'UD_IMPERSONATED_SERVICE_ACCOUNT_NAME'] env: [ 'BAZEL_REMOTE_CACHE=https://storage.googleapis.com/${_CACHE_BUCKET}/bazel-cache/${_DISTRO}-${_BUILD_NAME}', 'LIBRARIES=${_LIBRARIES}', diff --git a/google/cloud/universe_domain/integration_tests/BUILD.bazel b/google/cloud/universe_domain/integration_tests/BUILD.bazel new file mode 100644 index 0000000000000..e9fb8da24356e --- /dev/null +++ b/google/cloud/universe_domain/integration_tests/BUILD.bazel @@ -0,0 +1,35 @@ +# Copyright 2024 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. + +package(default_visibility = ["//visibility:private"]) + +licenses(["notice"]) # Apache 2.0 + +cc_test( + name = "impersonation_tests", + timeout = "long", + srcs = ["impersonation_tests.cc"], + tags = [ + "integration-test", + "ud-only", + ], + deps = [ + "//:common", + "//:experimental-universe_domain", + "//google/cloud/testing_util:google_cloud_cpp_testing_private", + "@com_google_googletest//:gtest_main", + "@google_cloud_cpp//:compute", + "@google_cloud_cpp//:kms", + ], +) diff --git a/google/cloud/universe_domain/integration_tests/impersonation_tests.cc b/google/cloud/universe_domain/integration_tests/impersonation_tests.cc new file mode 100644 index 0000000000000..de766e76e59a6 --- /dev/null +++ b/google/cloud/universe_domain/integration_tests/impersonation_tests.cc @@ -0,0 +1,112 @@ +// Copyright 2024 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. + +#include "google/cloud/compute/disks/v1/disks_client.h" +#include "google/cloud/compute/disks/v1/disks_options.h" +#include "google/cloud/kms/v1/key_management_client.h" +#include "google/cloud/kms/v1/key_management_options.h" +#include "google/cloud/internal/getenv.h" +#include "google/cloud/internal/rest_options.h" +#include "google/cloud/location.h" +#include "google/cloud/testing_util/integration_test.h" +#include "google/cloud/testing_util/status_matchers.h" +#include "google/cloud/universe_domain.h" +#include "google/cloud/universe_domain_options.h" +#include +#include + +namespace google { +namespace cloud { +namespace universe_domain { +GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN +namespace { + +namespace gc = ::google::cloud; +using ::google::cloud::testing_util::StatusIs; + +class DomainUniverseImpersonationTest + : public ::google::cloud::testing_util::IntegrationTest { + protected: + void SetUp() override { + project_id_ = gc::internal::GetEnv("UD_PROJECT").value_or(""); + ASSERT_FALSE(project_id_.empty()); + zone_id_ = gc::internal::GetEnv("UD_ZONE").value_or(""); + ASSERT_FALSE(zone_id_.empty()); + region_id_ = gc::internal::GetEnv("UD_REGION").value_or(""); + ASSERT_FALSE(region_id_.empty()); + impersonated_sa_ = + gc::internal::GetEnv("UD_IMPERSONATED_SERVICE_ACCOUNT_NAME") + .value_or(""); + ASSERT_FALSE(impersonated_sa_.empty()); + std::string const sa_key_file = + gc::internal::GetEnv("UD_SA_KEY_FILE").value_or(""); + ASSERT_FALSE(sa_key_file.empty()); + + auto is = std::ifstream(sa_key_file); + is.exceptions(std::ios::badbit); + credential_ = std::string(std::istreambuf_iterator(is.rdbuf()), {}); + } + + std::string project_id_; + std::string zone_id_; + std::string region_id_; + std::string impersonated_sa_; + std::string credential_; +}; + +TEST_F(DomainUniverseImpersonationTest, SAToSAImpersonationRest) { + namespace disks = ::google::cloud::compute_disks_v1; + + gc::Options options; + options.set( + google::cloud::MakeImpersonateServiceAccountCredentials( + google::cloud::MakeServiceAccountCredentials(credential_), + impersonated_sa_)); + + auto ud_options = gc::AddUniverseDomainOption(gc::ExperimentalTag{}, options); + ASSERT_STATUS_OK(ud_options); + + auto client = disks::DisksClient(disks::MakeDisksConnectionRest(*ud_options)); + + for (auto disk : client.ListDisks(project_id_, zone_id_)) { + EXPECT_STATUS_OK(disk); + } +} + +TEST_F(DomainUniverseImpersonationTest, SAToSAImpersonationGrpc) { + namespace kms = ::google::cloud::kms_v1; + + auto const location = gc::Location(project_id_, region_id_); + gc::Options options; + options.set( + google::cloud::MakeImpersonateServiceAccountCredentials( + google::cloud::MakeServiceAccountCredentials(credential_), + impersonated_sa_)); + + auto ud_options = gc::AddUniverseDomainOption(gc::ExperimentalTag{}, options); + ASSERT_STATUS_OK(ud_options); + + auto client = kms::KeyManagementServiceClient( + kms::MakeKeyManagementServiceConnection(*ud_options)); + + for (auto kr : client.ListKeyRings(location.FullName())) { + EXPECT_STATUS_OK(kr); + } +} + +} // namespace +GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END +} // namespace universe_domain +} // namespace cloud +} // namespace google