Skip to content

Commit

Permalink
Update cross-media-measurement-api dep for ListCertificates. (#1219)
Browse files Browse the repository at this point in the history
Updates the cross-media-measurement-api dependency to 0.42.0.
  • Loading branch information
SanjayVas authored and ple13 committed Aug 16, 2024
1 parent 66398fa commit 6e6c2cf
Show file tree
Hide file tree
Showing 13 changed files with 824 additions and 70 deletions.
4 changes: 2 additions & 2 deletions build/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def wfa_measurement_system_repositories():
wfa_repo_archive(
name = "wfa_measurement_proto",
repo = "cross-media-measurement-api",
sha256 = "ec802fd4f218874047a2e6e6b4be0a4718ab2a98551c0edfaacf5f94f856eb84",
version = "0.41.0",
sha256 = "b6ee5ff56c8c8ec8f6f44c93fe273d4120779dcd0954e9d69929137da2b2a4a7",
version = "0.42.0",
)

wfa_repo_archive(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package org.wfanet.measurement.kingdom.deploy.gcloud.spanner

import io.grpc.Status
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.singleOrNull
import org.wfanet.measurement.common.grpc.failGrpc
import org.wfanet.measurement.common.grpc.grpcRequire
Expand All @@ -28,6 +30,7 @@ import org.wfanet.measurement.internal.kingdom.CertificatesGrpcKt.CertificatesCo
import org.wfanet.measurement.internal.kingdom.GetCertificateRequest
import org.wfanet.measurement.internal.kingdom.ReleaseCertificateHoldRequest
import org.wfanet.measurement.internal.kingdom.RevokeCertificateRequest
import org.wfanet.measurement.internal.kingdom.StreamCertificatesRequest
import org.wfanet.measurement.kingdom.deploy.common.DuchyIds
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.common.CertSubjectKeyIdAlreadyExistsException
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.common.CertificateNotFoundException
Expand All @@ -37,6 +40,7 @@ import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.common.DuchyNotFound
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.common.KingdomInternalException
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.common.MeasurementConsumerNotFoundException
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.common.ModelProviderNotFoundException
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.queries.StreamCertificates
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.readers.BaseSpannerReader
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.readers.CertificateReader
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.writers.CreateCertificate
Expand Down Expand Up @@ -111,6 +115,27 @@ class SpannerCertificatesService(
return certificateResult.certificate
}

override fun streamCertificates(request: StreamCertificatesRequest): Flow<Certificate> {
@Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") // Protobuf enum fields cannot be null.
val parentType: CertificateReader.ParentType =
when (request.filter.parentCase) {
StreamCertificatesRequest.Filter.ParentCase.EXTERNAL_DATA_PROVIDER_ID ->
CertificateReader.ParentType.DATA_PROVIDER
StreamCertificatesRequest.Filter.ParentCase.EXTERNAL_MEASUREMENT_CONSUMER_ID ->
CertificateReader.ParentType.MEASUREMENT_CONSUMER
StreamCertificatesRequest.Filter.ParentCase.EXTERNAL_DUCHY_ID ->
CertificateReader.ParentType.DUCHY
StreamCertificatesRequest.Filter.ParentCase.EXTERNAL_MODEL_PROVIDER_ID ->
CertificateReader.ParentType.MODEL_PROVIDER
StreamCertificatesRequest.Filter.ParentCase.PARENT_NOT_SET ->
throw Status.INVALID_ARGUMENT.withDescription("filter.parent is required")
.asRuntimeException()
}
val query = StreamCertificates(parentType, request.filter, request.limit)

return query.execute(client.singleUse()).map { it.certificate }
}

override suspend fun revokeCertificate(request: RevokeCertificateRequest): Certificate {
grpcRequire(request.parentCase != RevokeCertificateRequest.ParentCase.PARENT_NOT_SET) {
"RevokeCertificateRequest is missing parent field"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@ sealed class KingdomInternalException : Exception {
val code: ErrorCode
protected abstract val context: Map<String, String>

constructor(code: ErrorCode) : super() {
constructor(code: ErrorCode, message: String, cause: Throwable? = null) : super(message, cause) {
this.code = code
}

constructor(code: ErrorCode, buildMessage: () -> String) : super(buildMessage()) {
this.code = code
}
constructor(code: ErrorCode, buildMessage: () -> String) : this(code, message = buildMessage())

fun asStatusRuntimeException(
statusCode: Status.Code,
Expand Down Expand Up @@ -281,8 +279,9 @@ class MeasurementEtagMismatchException(
}

class CertSubjectKeyIdAlreadyExistsException(
provideDescription: () -> String = { "Cert subject key id already exists" }
) : KingdomInternalException(ErrorCode.CERT_SUBJECT_KEY_ID_ALREADY_EXISTS, provideDescription) {
cause: Throwable? = null,
message: String = "Cert subject key id already exists",
) : KingdomInternalException(ErrorCode.CERT_SUBJECT_KEY_ID_ALREADY_EXISTS, message, cause) {
override val context
get() = emptyMap<String, String>()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ kt_jvm_library(
"//src/main/kotlin/org/wfanet/measurement/common/identity",
"//src/main/kotlin/org/wfanet/measurement/kingdom/deploy/gcloud/spanner/common",
"//src/main/kotlin/org/wfanet/measurement/kingdom/deploy/gcloud/spanner/readers",
"//src/main/proto/wfa/measurement/internal/kingdom:certificates_service_kt_jvm_grpc_proto",
"//src/main/proto/wfa/measurement/internal/kingdom:data_provider_kt_jvm_proto",
"@wfa_common_jvm//imports/java/com/google/cloud/spanner",
"@wfa_common_jvm//imports/kotlin/kotlinx/coroutines:core",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright 2023 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.kingdom.deploy.gcloud.spanner.queries

import com.google.cloud.spanner.Statement
import org.wfanet.measurement.common.identity.ExternalId
import org.wfanet.measurement.gcloud.common.toGcloudByteArray
import org.wfanet.measurement.gcloud.common.toGcloudTimestamp
import org.wfanet.measurement.gcloud.spanner.appendClause
import org.wfanet.measurement.gcloud.spanner.bind
import org.wfanet.measurement.internal.kingdom.StreamCertificatesRequest
import org.wfanet.measurement.kingdom.deploy.gcloud.spanner.readers.CertificateReader

class StreamCertificates(
parentType: CertificateReader.ParentType,
requestFilter: StreamCertificatesRequest.Filter,
limit: Int = 0
) : SimpleSpannerQuery<CertificateReader.Result>() {
override val reader =
CertificateReader(parentType).fillStatementBuilder {
bindWhereClause(parentType, requestFilter)
appendOrderByClause(parentType)
if (limit > 0) {
bind(Params.LIMIT).to(limit.toLong())
appendClause("LIMIT @${Params.LIMIT}")
}
}

private object Params {
const val LIMIT = "limit"
const val EXTERNAL_PARENT_ID = "externalParentId"
const val EXTERNAL_CERTIFICATE_ID = "externalCertificateId"
const val NOT_VALID_BEFORE = "notValidBefore"
const val SUBJECT_KEY_IDENTIFIERS = "subjectKeyIdentifiers"
}

companion object {
private fun Statement.Builder.appendOrderByClause(parentType: CertificateReader.ParentType) {
val expressions =
mutableListOf("NotValidBefore DESC", parentType.externalCertificateIdColumnName)
val externalParentIdColumn: String? = parentType.externalIdColumnName
if (externalParentIdColumn != null) {
expressions.add(externalParentIdColumn)
}

appendClause("ORDER BY " + expressions.joinToString(", "))
}

private fun Statement.Builder.bindWhereClause(
parentType: CertificateReader.ParentType,
requestFilter: StreamCertificatesRequest.Filter
) {
val conjuncts = mutableListOf<String>()
if (requestFilter.hasAfter()) {
val externalCertificateIdColumn = parentType.externalCertificateIdColumnName
val externalParentIdColumn: String? = parentType.externalIdColumnName
val conjunct =
if (externalParentIdColumn == null) {
"""
NotValidBefore < @${Params.NOT_VALID_BEFORE} OR (
NotValidBefore = @${Params.NOT_VALID_BEFORE} AND
$externalCertificateIdColumn > @${Params.EXTERNAL_CERTIFICATE_ID}
)
"""
.trimIndent()
} else {
bind(Params.EXTERNAL_PARENT_ID to requestFilter.getExternalParentId(parentType))

"""
NotValidBefore < @${Params.NOT_VALID_BEFORE} OR (
NotValidBefore = @${Params.NOT_VALID_BEFORE} AND (
$externalCertificateIdColumn > @${Params.EXTERNAL_CERTIFICATE_ID} OR (
$externalCertificateIdColumn = @${Params.EXTERNAL_CERTIFICATE_ID} AND
$externalParentIdColumn > @${Params.EXTERNAL_PARENT_ID}
)
)
)
"""
.trimIndent()
}

bind(Params.NOT_VALID_BEFORE).to(requestFilter.after.notValidBefore.toGcloudTimestamp())
bind(Params.EXTERNAL_CERTIFICATE_ID).to(requestFilter.after.externalCertificateId)
conjuncts.add(conjunct)
}
if (requestFilter.subjectKeyIdentifiersList.isNotEmpty()) {
bind(Params.SUBJECT_KEY_IDENTIFIERS)
.toBytesArray(requestFilter.subjectKeyIdentifiersList.map { it.toGcloudByteArray() })
conjuncts.add("SubjectKeyIdentifier IN UNNEST(@${Params.SUBJECT_KEY_IDENTIFIERS})")
}

if (conjuncts.isEmpty()) {
return
}

appendClause("WHERE ")
append(conjuncts.joinToString(" AND "))
}

private fun StreamCertificatesRequest.Filter.getExternalParentId(
parentType: CertificateReader.ParentType
): ExternalId {
val value: Long =
when (parentType) {
CertificateReader.ParentType.DATA_PROVIDER -> externalDataProviderId
CertificateReader.ParentType.MEASUREMENT_CONSUMER -> externalMeasurementConsumerId
CertificateReader.ParentType.MODEL_PROVIDER -> externalModelProviderId
CertificateReader.ParentType.DUCHY ->
error("ParentType $parentType does not have an integer external ID")
}
return ExternalId(value)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class CreateCertificate(private val certificate: Certificate) :

override suspend fun handleSpannerException(e: SpannerException): Certificate? {
when (e.errorCode) {
SpannerErrorCode.ALREADY_EXISTS -> throw CertSubjectKeyIdAlreadyExistsException()
SpannerErrorCode.ALREADY_EXISTS -> throw CertSubjectKeyIdAlreadyExistsException(e)
else -> throw e
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ kt_jvm_library(
"//src/main/kotlin/org/wfanet/measurement/api/v2alpha:resource_key",
"//src/main/proto/wfa/measurement/api/v2alpha:certificate_kt_jvm_proto",
"//src/main/proto/wfa/measurement/api/v2alpha:certificates_service_kt_jvm_grpc_proto",
"//src/main/proto/wfa/measurement/api/v2alpha:page_token_kt_jvm_proto",
"//src/main/proto/wfa/measurement/internal/kingdom:certificate_kt_jvm_proto",
"//src/main/proto/wfa/measurement/internal/kingdom:certificates_service_kt_jvm_grpc_proto",
"@wfa_common_jvm//src/main/kotlin/org/wfanet/measurement/common",
Expand Down
Loading

0 comments on commit 6e6c2cf

Please sign in to comment.