diff --git a/src/main/kotlin/org/wfanet/measurement/access/common/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/access/common/BUILD.bazel index e760550192e..e5651b00267 100644 --- a/src/main/kotlin/org/wfanet/measurement/access/common/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/access/common/BUILD.bazel @@ -2,6 +2,7 @@ load("@wfa_rules_kotlin_jvm//kotlin:defs.bzl", "kt_jvm_library") package(default_visibility = [ "//src/main/kotlin/org/wfanet/measurement/access:__subpackages__", + "//src/main/kotlin/org/wfanet/measurement/integration:__subpackages__", "//src/test/kotlin/org/wfanet/measurement/access:__subpackages__", ]) diff --git a/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/BUILD.bazel index c5460da61c9..eb4ccc671e5 100644 --- a/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/BUILD.bazel @@ -5,6 +5,7 @@ load("//src/main/docker:macros.bzl", "java_image") package( default_visibility = [ "//src/main/kotlin/org/wfanet/measurement/access/deploy:__subpackages__", + "//src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud:__subpackages__", "//src/test/kotlin/org/wfanet/measurement/access/deploy:__subpackages__", ], ) diff --git a/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/testing/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/testing/BUILD.bazel index bb900ca73f5..60462f581d8 100644 --- a/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/testing/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/testing/BUILD.bazel @@ -3,6 +3,7 @@ load("@wfa_rules_kotlin_jvm//kotlin:defs.bzl", "kt_jvm_library") package( default_testonly = True, default_visibility = [ + "//src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud:__subpackages__", "//src/test/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner:__subpackages__", ], ) diff --git a/src/main/kotlin/org/wfanet/measurement/access/service/internal/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/access/service/internal/BUILD.bazel index bcfcde99557..e5a0c5ae9e9 100644 --- a/src/main/kotlin/org/wfanet/measurement/access/service/internal/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/access/service/internal/BUILD.bazel @@ -4,6 +4,7 @@ package( default_visibility = [ "//src/main/kotlin/org/wfanet/measurement/access/deploy:__subpackages__", "//src/main/kotlin/org/wfanet/measurement/access/service:__subpackages__", + "//src/main/kotlin/org/wfanet/measurement/integration:__subpackages__", "//src/test/kotlin/org/wfanet/measurement/access/service:__subpackages__", ], ) diff --git a/src/main/kotlin/org/wfanet/measurement/access/service/v1alpha/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/access/service/v1alpha/BUILD.bazel index c383f034ce9..4d248299e44 100644 --- a/src/main/kotlin/org/wfanet/measurement/access/service/v1alpha/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/access/service/v1alpha/BUILD.bazel @@ -5,6 +5,7 @@ package( default_visibility = [ "//src/main/kotlin/org/wfanet/measurement/access/deploy:__subpackages__", test_target(":__pkg__"), + "//src/main/kotlin/org/wfanet/measurement/integration/common:__pkg__", ], ) diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/AccessServicesFactory.kt b/src/main/kotlin/org/wfanet/measurement/integration/common/AccessServicesFactory.kt new file mode 100644 index 00000000000..1a1515afd40 --- /dev/null +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/AccessServicesFactory.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2024 The Cross-Media Measurement Authors + * + * 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 org.wfanet.measurement.integration.common + +import org.junit.rules.TestRule +import org.wfanet.measurement.access.common.TlsClientPrincipalMapping +import org.wfanet.measurement.access.service.internal.PermissionMapping +import org.wfanet.measurement.access.service.internal.Services as AccessInternalServices + +interface AccessServicesFactory : TestRule { + fun create( + permissionMapping: PermissionMapping, + tlsClientMapping: TlsClientPrincipalMapping, + ): AccessInternalServices +} diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/integration/common/BUILD.bazel index 8764c226d65..b072eebe505 100644 --- a/src/main/kotlin/org/wfanet/measurement/integration/common/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/BUILD.bazel @@ -5,6 +5,7 @@ load("//src/main/proto/wfa/measurement/internal/kingdom:all_protos.bzl", "KINGDO package( default_testonly = True, default_visibility = [ + "//src/main/kotlin/org/wfanet/measurement/integration:__subpackages__", "//src/main/kotlin/org/wfanet/measurement/loadtest:__subpackages__", "//src/test/kotlin/org/wfanet/measurement/integration:__subpackages__", "//src/test/kotlin/org/wfanet/measurement/loadtest:__subpackages__", @@ -101,6 +102,7 @@ kt_jvm_library( "//src/main/k8s/testing/secretfiles:all_der_files", "//src/main/k8s/testing/secretfiles:all_root_certs.pem", "//src/main/k8s/testing/secretfiles:all_tink_keysets", + "//src/main/proto/wfa/measurement/reporting/v2alpha:permissions_config.textproto", ], deps = [ "//src/main/kotlin/org/wfanet/measurement/api/v2alpha:resource_key", @@ -108,6 +110,7 @@ kt_jvm_library( "//src/main/kotlin/org/wfanet/measurement/loadtest/resourcesetup:resource_setup", "//src/main/kotlin/org/wfanet/measurement/populationdataprovider:population_requisition_fulfiller", "//src/main/proto/wfa/measurement/config:duchy_cert_config_kt_jvm_proto", + "//src/main/proto/wfa/measurement/config/access:permissions_config_kt_jvm_proto", "//src/main/proto/wfa/measurement/internal/duchy/config:protocols_setup_config_kt_jvm_proto", "//src/main/proto/wfa/measurement/internal/kingdom:duchy_id_config_kt_jvm_proto", "//src/main/proto/wfa/measurement/internal/kingdom:protocol_config_config_kt_jvm_proto", @@ -255,6 +258,35 @@ kt_jvm_library( ], ) +kt_jvm_library( + name = "access_services_factory", + srcs = ["AccessServicesFactory.kt"], + visibility = [ + "//src/main/kotlin/org/wfanet/measurement/integration:__subpackages__", + ], + deps = [ + "//src/main/kotlin/org/wfanet/measurement/access/common:tls_client_principal_mapping", + "//src/main/kotlin/org/wfanet/measurement/access/service/internal:permission_mapping", + "//src/main/kotlin/org/wfanet/measurement/access/service/internal:services", + "@wfa_common_jvm//imports/java/org/junit", + ], +) + +kt_jvm_library( + name = "in_process_access", + srcs = ["InProcessAccess.kt"], + visibility = [ + "//src/main/kotlin/org/wfanet/measurement/integration:__subpackages__", + ], + deps = [ + "//src/main/kotlin/org/wfanet/measurement/access/service/internal:services", + "//src/main/kotlin/org/wfanet/measurement/access/service/v1alpha:services", + "@wfa_common_jvm//imports/java/org/junit", + "@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/common/grpc/testing", + "@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/common/testing", + ], +) + kt_jvm_library( name = "in_process_life_of_a_measurement_integration_test", srcs = [ diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/Configs.kt b/src/main/kotlin/org/wfanet/measurement/integration/common/Configs.kt index 7e2500c1d61..8e0f9b26909 100644 --- a/src/main/kotlin/org/wfanet/measurement/integration/common/Configs.kt +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/Configs.kt @@ -36,6 +36,7 @@ import org.wfanet.measurement.common.parseTextProto import org.wfanet.measurement.common.readByteString import org.wfanet.measurement.common.toInstant import org.wfanet.measurement.common.toJson +import org.wfanet.measurement.config.access.PermissionsConfig import org.wfanet.measurement.consent.client.common.toEncryptionPublicKey import org.wfanet.measurement.internal.duchy.config.ProtocolsSetupConfig import org.wfanet.measurement.internal.kingdom.DuchyIdConfig @@ -44,12 +45,10 @@ import org.wfanet.measurement.internal.kingdom.Llv2ProtocolConfigConfig import org.wfanet.measurement.kingdom.deploy.common.DuchyIds import org.wfanet.measurement.loadtest.resourcesetup.EntityContent +private const val REPO_NAME = "wfa_measurement_system" + private val SECRET_FILES_PATH: Path = - checkNotNull( - getRuntimePath( - Paths.get("wfa_measurement_system", "src", "main", "k8s", "testing", "secretfiles") - ) - ) + checkNotNull(getRuntimePath(Paths.get(REPO_NAME, "src", "main", "k8s", "testing", "secretfiles"))) val AGGREGATOR_PROTOCOLS_SETUP_CONFIG: ProtocolsSetupConfig = loadTextProto( @@ -111,6 +110,27 @@ val ALL_DUCHIES = ) } +val PERMISSIONS_CONFIG: PermissionsConfig = + parseTextProto( + checkNotNull( + getRuntimePath( + Paths.get( + REPO_NAME, + "src", + "main", + "proto", + "wfa", + "measurement", + "reporting", + "v2alpha", + "permissions_config.textproto", + ) + ) + ) + .toFile(), + PermissionsConfig.getDefaultInstance(), + ) + val ALL_EDP_WITH_HMSS_CAPABILITIES_DISPLAY_NAMES = listOf("edp1", "edp3") val ALL_EDP_WITHOUT_HMSS_CAPABILITIES_DISPLAY_NAMES = listOf("edp2") val ALL_EDP_DISPLAY_NAMES = diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/InProcessAccess.kt b/src/main/kotlin/org/wfanet/measurement/integration/common/InProcessAccess.kt new file mode 100644 index 00000000000..2ffbd047263 --- /dev/null +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/InProcessAccess.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2024 The Cross-Media Measurement Authors + * + * 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 org.wfanet.measurement.integration.common + +import io.grpc.Channel +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement +import org.wfanet.measurement.access.service.internal.Services as InternalServices +import org.wfanet.measurement.access.service.v1alpha.Services +import org.wfanet.measurement.common.grpc.testing.GrpcTestServerRule +import org.wfanet.measurement.common.testing.chainRulesSequentially + +class InProcessAccess( + verboseGrpcLogging: Boolean, + private val getInternalServices: () -> InternalServices, +) : TestRule { + private val internalAccessServer = + GrpcTestServerRule(logAllRequests = verboseGrpcLogging) { + val services = getInternalServices().toList() + for (service in services) { + addService(service) + } + } + + private val accessServer = + GrpcTestServerRule(logAllRequests = verboseGrpcLogging) { + val internalChannel = internalAccessServer.channel + val services = Services.build(internalChannel).toList() + for (service in services) { + addService(service) + } + } + + val channel: Channel + get() = accessServer.channel + + override fun apply(base: Statement, description: Description): Statement { + return chainRulesSequentially(internalAccessServer, accessServer).apply(base, description) + } +} diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/BUILD.bazel index 1059d9facd6..36458ffebd5 100644 --- a/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/BUILD.bazel @@ -18,6 +18,7 @@ kt_jvm_library( deps = [ ":in_process_reporting_server", "//src/main/kotlin/org/wfanet/measurement/api/v2alpha/testing", + "//src/main/kotlin/org/wfanet/measurement/integration/common:access_services_factory", "//src/main/kotlin/org/wfanet/measurement/integration/common:in_process_cmms_components", "//src/main/kotlin/org/wfanet/measurement/integration/common:synthetic_generation_specs", "//src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/identity:reporting_principal_identity", @@ -48,6 +49,9 @@ kt_jvm_library( "//src/main/k8s/testing/secretfiles:secret_files", ], deps = [ + "//src/main/kotlin/org/wfanet/measurement/integration/common:access_services_factory", + "//src/main/kotlin/org/wfanet/measurement/integration/common:configs", + "//src/main/kotlin/org/wfanet/measurement/integration/common:in_process_access", "//src/main/kotlin/org/wfanet/measurement/measurementconsumer/stats:variances", "//src/main/kotlin/org/wfanet/measurement/reporting/deploy/v2/common/server:internal_reporting_server", "//src/main/kotlin/org/wfanet/measurement/reporting/service/api:cel_env_provider", diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessLifeOfAReportIntegrationTest.kt b/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessLifeOfAReportIntegrationTest.kt index ae968ab2652..37fa83d302f 100644 --- a/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessLifeOfAReportIntegrationTest.kt +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessLifeOfAReportIntegrationTest.kt @@ -32,12 +32,26 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking +import org.junit.Before import org.junit.BeforeClass import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement +import org.wfanet.measurement.access.client.v1alpha.TrustedPrincipalAuthInterceptor +import org.wfanet.measurement.access.service.PermissionKey +import org.wfanet.measurement.access.v1alpha.PoliciesGrpc +import org.wfanet.measurement.access.v1alpha.PolicyKt +import org.wfanet.measurement.access.v1alpha.PrincipalKt +import org.wfanet.measurement.access.v1alpha.PrincipalsGrpc +import org.wfanet.measurement.access.v1alpha.RolesGrpc +import org.wfanet.measurement.access.v1alpha.createPolicyRequest +import org.wfanet.measurement.access.v1alpha.createPrincipalRequest +import org.wfanet.measurement.access.v1alpha.createRoleRequest +import org.wfanet.measurement.access.v1alpha.policy +import org.wfanet.measurement.access.v1alpha.principal +import org.wfanet.measurement.access.v1alpha.role import org.wfanet.measurement.api.v2alpha.DataProviderCertificateKey import org.wfanet.measurement.api.v2alpha.DataProvidersGrpcKt.DataProvidersCoroutineStub import org.wfanet.measurement.api.v2alpha.EventGroupKt as CmmsEventGroupKt @@ -65,6 +79,7 @@ import org.wfanet.measurement.config.reporting.EncryptionKeyPairConfigKt.princip import org.wfanet.measurement.config.reporting.encryptionKeyPairConfig import org.wfanet.measurement.config.reporting.measurementConsumerConfig import org.wfanet.measurement.consent.client.dataprovider.encryptMetadata +import org.wfanet.measurement.integration.common.AccessServicesFactory import org.wfanet.measurement.integration.common.InProcessCmmsComponents import org.wfanet.measurement.integration.common.InProcessDuchy import org.wfanet.measurement.integration.common.SyntheticGenerationSpecs @@ -72,6 +87,7 @@ import org.wfanet.measurement.integration.common.reporting.v2.identity.withPrinc import org.wfanet.measurement.kingdom.deploy.common.service.DataServices import org.wfanet.measurement.loadtest.dataprovider.EventQuery import org.wfanet.measurement.loadtest.dataprovider.MeasurementResults +import org.wfanet.measurement.loadtest.measurementconsumer.MeasurementConsumerData import org.wfanet.measurement.loadtest.measurementconsumer.MetadataSyntheticGeneratorEventQuery import org.wfanet.measurement.reporting.deploy.v2.common.server.InternalReportingServer import org.wfanet.measurement.reporting.v2alpha.EventGroup @@ -121,6 +137,7 @@ abstract class InProcessLifeOfAReportIntegrationTest( String, ComputationLogEntriesGrpcKt.ComputationLogEntriesCoroutineStub, ) -> InProcessDuchy.DuchyDependencies >, + accessServicesFactory: AccessServicesFactory, ) { private val inProcessCmmsComponents: InProcessCmmsComponents = InProcessCmmsComponents(kingdomDataServicesRule, duchyDependenciesRule) @@ -172,6 +189,7 @@ abstract class InProcessLifeOfAReportIntegrationTest( return InProcessReportingServer( internalReportingServerServices, + accessServicesFactory, inProcessCmmsComponents.kingdom.publicApiChannel, encryptionKeyPairConfig, SECRETS_DIR, @@ -203,6 +221,92 @@ abstract class InProcessLifeOfAReportIntegrationTest( reportingServerRule, ) + private lateinit var credentials: TrustedPrincipalAuthInterceptor.Credentials + + @Before + fun createAccessPolicy() { + val measurementConsumerData: MeasurementConsumerData = + inProcessCmmsComponents.getMeasurementConsumerData() + val accessChannel = reportingServer.accessChannel + + val rolesStub = RolesGrpc.newBlockingStub(accessChannel) + val mcResourceType = "halo.wfanet.org/MeasurementConsumer" + val mcUserRole = + rolesStub.createRole( + createRoleRequest { + roleId = "mcUser" + role = role { + resourceTypes += mcResourceType + permissions += + PERMISSIONS_CONFIG.permissionsMap + .filterValues { it.protectedResourceTypesList.contains(mcResourceType) } + .keys + .map { PermissionKey(it).toName() } + } + } + ) + val rootResourceType = "reporting.halo-cmm.org/Root" + val kingdomUserRole = + rolesStub.createRole( + createRoleRequest { + roleId = "kingdomUser" + role = role { + resourceTypes += rootResourceType + permissions += + PERMISSIONS_CONFIG.permissionsMap + .filterValues { it.protectedResourceTypesList.contains(rootResourceType) } + .keys + .map { PermissionKey(it).toName() } + } + } + ) + + val principalsStub = PrincipalsGrpc.newBlockingStub(accessChannel) + val principal = + principalsStub.createPrincipal( + createPrincipalRequest { + principalId = "mc-user" + this.principal = principal { + user = + PrincipalKt.oAuthUser { + issuer = "example.com" + subject = "mc-user@example.com" + } + } + } + ) + + val policiesStub = PoliciesGrpc.newBlockingStub(accessChannel) + policiesStub.createPolicy( + createPolicyRequest { + policyId = "test-mc-policy" + policy = policy { + protectedResource = measurementConsumerData.name + bindings += + PolicyKt.binding { + this.role = mcUserRole.name + members += principal.name + } + } + } + ) + policiesStub.createPolicy( + createPolicyRequest { + policyId = "test-root-policy" + policy = policy { + protectedResource = "" // Root + bindings += + PolicyKt.binding { + this.role = kingdomUserRole.name + members += principal.name + } + } + } + ) + + credentials = TrustedPrincipalAuthInterceptor.Credentials(principal, setOf("reporting.*")) + } + private val publicKingdomMeasurementConsumersClient by lazy { MeasurementConsumersCoroutineStub(inProcessCmmsComponents.kingdom.publicApiChannel) } diff --git a/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessReportingServer.kt b/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessReportingServer.kt index 8ae8a79ccf3..d593341a179 100644 --- a/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessReportingServer.kt +++ b/src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2/InProcessReportingServer.kt @@ -33,6 +33,8 @@ import kotlinx.coroutines.runBlocking import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement +import org.wfanet.measurement.access.common.TlsClientPrincipalMapping +import org.wfanet.measurement.access.service.internal.PermissionMapping import org.wfanet.measurement.api.v2alpha.CertificatesGrpcKt.CertificatesCoroutineStub as PublicKingdomCertificatesCoroutineStub import org.wfanet.measurement.api.v2alpha.DataProvidersGrpcKt.DataProvidersCoroutineStub as PublicKingdomDataProvidersCoroutineStub import org.wfanet.measurement.api.v2alpha.EventGroupMetadataDescriptorsGrpcKt.EventGroupMetadataDescriptorsCoroutineStub as PublicKingdomEventGroupMetadataDescriptorsCoroutineStub @@ -48,12 +50,16 @@ import org.wfanet.measurement.common.grpc.withVerboseLogging import org.wfanet.measurement.common.readByteString import org.wfanet.measurement.common.testing.CloseableResource import org.wfanet.measurement.common.testing.chainRulesSequentially +import org.wfanet.measurement.config.AuthorityKeyToPrincipalMap import org.wfanet.measurement.config.reporting.EncryptionKeyPairConfig import org.wfanet.measurement.config.reporting.MeasurementConsumerConfig import org.wfanet.measurement.config.reporting.MetricSpecConfig import org.wfanet.measurement.config.reporting.MetricSpecConfigKt import org.wfanet.measurement.config.reporting.measurementConsumerConfigs import org.wfanet.measurement.config.reporting.metricSpecConfig +import org.wfanet.measurement.integration.common.AccessServicesFactory +import org.wfanet.measurement.integration.common.InProcessAccess +import org.wfanet.measurement.integration.common.PERMISSIONS_CONFIG import org.wfanet.measurement.internal.reporting.v2.MeasurementConsumersGrpcKt.MeasurementConsumersCoroutineStub as InternalMeasurementConsumersCoroutineStub import org.wfanet.measurement.internal.reporting.v2.MeasurementsGrpcKt.MeasurementsCoroutineStub as InternalMeasurementsCoroutineStub import org.wfanet.measurement.internal.reporting.v2.MetricCalculationSpecsGrpcKt.MetricCalculationSpecsCoroutineStub as InternalMetricCalculationSpecsCoroutineStub @@ -81,6 +87,7 @@ import org.wfanet.measurement.reporting.v2alpha.MetricsGrpcKt.MetricsCoroutineSt /** TestRule that starts and stops all Reporting Server gRPC services. */ class InProcessReportingServer( private val internalReportingServerServices: InternalReportingServer.Services, + private val accessServicesFactory: AccessServicesFactory, kingdomPublicApiChannel: Channel, private val encryptionKeyPairConfig: EncryptionKeyPairConfig, private val signingPrivateKeyDir: File, @@ -102,7 +109,9 @@ class InProcessReportingServer( private val publicKingdomEventGroupsClient = PublicKingdomEventGroupsCoroutineStub(kingdomPublicApiChannel) - private val internalApiChannel by lazy { internalReportingServer.channel } + private val internalApiChannel + get() = internalReportingServer.channel + private val internalMeasurementConsumersClient by lazy { InternalMeasurementConsumersCoroutineStub(internalApiChannel) } @@ -130,6 +139,14 @@ class InProcessReportingServer( lateinit var metricSpecConfig: MetricSpecConfig + private val access = + InProcessAccess(verboseGrpcLogging) { + val tlsClientMapping = + TlsClientPrincipalMapping(AuthorityKeyToPrincipalMap.getDefaultInstance()) + val permissionMapping = PermissionMapping(PERMISSIONS_CONFIG) + accessServicesFactory.create(permissionMapping, tlsClientMapping) + } + private val celEnvCacheProvider = object : CloseableResource({ @@ -253,9 +270,19 @@ class InProcessReportingServer( val publicApiChannel: Channel get() = publicApiServer.channel + /** gRPC [Channel] for Access API. */ + val accessChannel: Channel + get() = access.channel + override fun apply(base: Statement, description: Description): Statement { publicApiServer = createPublicApiTestServerRule() - return chainRulesSequentially(internalReportingServer, celEnvCacheProvider, publicApiServer) + return chainRulesSequentially( + internalReportingServer, + accessServicesFactory, + access, + celEnvCacheProvider, + publicApiServer, + ) .apply(base, description) } diff --git a/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel b/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel index 470892f1dd1..a000a9e4d60 100644 --- a/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel +++ b/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel @@ -40,3 +40,18 @@ kt_jvm_library( "@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/gcloud/spanner/testing", ], ) + +kt_jvm_library( + name = "spanner_access_services_factory", + srcs = ["SpannerAccessServicesFactory.kt"], + deps = [ + "//src/main/kotlin/org/wfanet/measurement/access/common:tls_client_principal_mapping", + "//src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner:internal_api_services", + "//src/main/kotlin/org/wfanet/measurement/access/deploy/gcloud/spanner/testing:schemata", + "//src/main/kotlin/org/wfanet/measurement/access/service/internal:permission_mapping", + "//src/main/kotlin/org/wfanet/measurement/access/service/internal:services", + "//src/main/kotlin/org/wfanet/measurement/integration/common:access_services_factory", + "@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/common/testing", + "@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/gcloud/spanner/testing", + ], +) diff --git a/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/SpannerAccessServicesFactory.kt b/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/SpannerAccessServicesFactory.kt new file mode 100644 index 00000000000..4e3784ef292 --- /dev/null +++ b/src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud/SpannerAccessServicesFactory.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2024 The Cross-Media Measurement Authors + * + * 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 org.wfanet.measurement.integration.deploy.gcloud + +import org.junit.runner.Description +import org.junit.runners.model.Statement +import org.wfanet.measurement.access.common.TlsClientPrincipalMapping +import org.wfanet.measurement.access.deploy.gcloud.spanner.InternalApiServices +import org.wfanet.measurement.access.deploy.gcloud.spanner.testing.Schemata +import org.wfanet.measurement.access.service.internal.PermissionMapping +import org.wfanet.measurement.access.service.internal.Services as AccessInternalServices +import org.wfanet.measurement.gcloud.spanner.testing.SpannerDatabaseAdmin +import org.wfanet.measurement.gcloud.spanner.testing.SpannerEmulatorDatabaseRule +import org.wfanet.measurement.integration.common.AccessServicesFactory + +class SpannerAccessServicesFactory(emulatorDatabaseAdmin: SpannerDatabaseAdmin) : + AccessServicesFactory { + private val spannerDatabase = + SpannerEmulatorDatabaseRule(emulatorDatabaseAdmin, Schemata.ACCESS_CHANGELOG_PATH) + + override fun create( + permissionMapping: PermissionMapping, + tlsClientMapping: TlsClientPrincipalMapping, + ): AccessInternalServices = + InternalApiServices.build(spannerDatabase.databaseClient, permissionMapping, tlsClientMapping) + + override fun apply(base: Statement, description: Description): Statement { + return spannerDatabase.apply(base, description) + } +} diff --git a/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel b/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel index 0f577aca006..23af915c8be 100644 --- a/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel +++ b/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/BUILD.bazel @@ -82,6 +82,7 @@ kt_jvm_library( "//src/main/kotlin/org/wfanet/measurement/integration/common/reporting/v2:in_process_life_of_a_report_integration_test", "//src/main/kotlin/org/wfanet/measurement/integration/deploy/common/postgres:postgres_duchy_dependency_provider_rule", "//src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud:kingdom_data_services_provider_rule", + "//src/main/kotlin/org/wfanet/measurement/integration/deploy/gcloud:spanner_access_services_factory", "//src/main/kotlin/org/wfanet/measurement/reporting/deploy/v2/common/server/postgres:services", "//src/main/kotlin/org/wfanet/measurement/reporting/deploy/v2/postgres/testing", "@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/common/db/r2dbc/postgres/testing:database_provider", diff --git a/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/GCloudInProcessLifeOfAReportV2IntegrationTest.kt b/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/GCloudInProcessLifeOfAReportV2IntegrationTest.kt index ef5d077dd09..95024e50f51 100644 --- a/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/GCloudInProcessLifeOfAReportV2IntegrationTest.kt +++ b/src/test/kotlin/org/wfanet/measurement/integration/deploy/gcloud/GCloudInProcessLifeOfAReportV2IntegrationTest.kt @@ -33,6 +33,7 @@ class GCloudInProcessLifeOfAReportV2IntegrationTest : InProcessLifeOfAReportIntegrationTest( KingdomDataServicesProviderRule(spannerEmulator), PostgresDuchyDependencyProviderRule(duchyDatabaseProvider, ALL_DUCHY_NAMES), + SpannerAccessServicesFactory(spannerEmulator), ) { override val internalReportingServerServices by lazy { PostgresServices.create(