diff --git a/docs/grpc/index.html b/docs/grpc/index.html index e97dd32d9d..30670c6418 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -3483,6 +3483,32 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + +
Method NameOption
PublicKey

NO_SIDE_EFFECTS

LegacyPublicKey

NO_SIDE_EFFECTS

+ +
@@ -5106,6 +5132,42 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListAttributes

NO_SIDE_EFFECTS

ListAttributeValues

NO_SIDE_EFFECTS

GetAttribute

NO_SIDE_EFFECTS

GetAttributeValuesByFqns

NO_SIDE_EFFECTS

+ +
@@ -5714,6 +5776,37 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListKeyAccessServers

NO_SIDE_EFFECTS

GetKeyAccessServer

NO_SIDE_EFFECTS

ListKeyAccessServerGrants

NO_SIDE_EFFECTS

+ +
@@ -6265,6 +6358,32 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + +
Method NameOption
GetNamespace

NO_SIDE_EFFECTS

ListNamespaces

NO_SIDE_EFFECTS

+ +
@@ -7214,6 +7333,47 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListResourceMappingGroups

NO_SIDE_EFFECTS

GetResourceMappingGroup

NO_SIDE_EFFECTS

ListResourceMappings

NO_SIDE_EFFECTS

ListResourceMappingsByGroupFqns

NO_SIDE_EFFECTS

GetResourceMapping

NO_SIDE_EFFECTS

+ +
@@ -8157,6 +8317,42 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method NameOption
ListSubjectMappings

NO_SIDE_EFFECTS

GetSubjectMapping

NO_SIDE_EFFECTS

ListSubjectConditionSets

NO_SIDE_EFFECTS

GetSubjectConditionSet

NO_SIDE_EFFECTS

+ +
@@ -9009,6 +9205,27 @@

Methods with HTTP bindings

+ + +

Methods with idempotency_level option

+ + + + + + + + + + + + + + + +
Method NameOption
GetWellKnownConfiguration

NO_SIDE_EFFECTS

+ +

Scalar Value Types

diff --git a/go.work.sum b/go.work.sum index b473435b06..3b76f7b56c 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,6 +1,7 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 h1:SRsZGA7aFnCZETmov57jwPrWuTmaZK6+4R4v5FUe1/c= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= +buf.build/gen/go/bufbuild/protovalidate-testing/protocolbuffers/go v1.31.0-20230824200732-8bc04916caea.1/go.mod h1:cJ4gQkiW4uPTUTI3+O2862OzMSTnzrFNwMauHLwPDPg= cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= diff --git a/protocol/go/kas/kas.pb.go b/protocol/go/kas/kas.pb.go index d2ebb9b6c8..eee98539af 100644 --- a/protocol/go/kas/kas.pb.go +++ b/protocol/go/kas/kas.pb.go @@ -452,42 +452,43 @@ var file_kas_kas_proto_rawDesc = []byte{ 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xc8, 0x02, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xce, 0x02, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x15, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x6b, 0x61, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x12, 0x75, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x27, - 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x6b, 0x61, 0x73, 0x5f, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x58, 0x0a, 0x06, 0x52, 0x65, 0x77, 0x72, 0x61, - 0x70, 0x12, 0x12, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, - 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x92, 0x41, 0x09, 0x4a, - 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, - 0x2a, 0x22, 0x0e, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x77, 0x72, 0x61, - 0x70, 0x42, 0xe2, 0x01, 0x92, 0x41, 0x73, 0x12, 0x71, 0x0a, 0x1a, 0x4f, 0x70, 0x65, 0x6e, 0x54, - 0x44, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2a, 0x4c, 0x0a, 0x12, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, - 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x12, 0x36, 0x68, 0x74, 0x74, - 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, - 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, - 0x4e, 0x53, 0x45, 0x32, 0x05, 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x2e, - 0x6b, 0x61, 0x73, 0x42, 0x08, 0x4b, 0x61, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, - 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, 0x61, 0x73, 0xa2, 0x02, 0x03, 0x4b, - 0x58, 0x58, 0xaa, 0x02, 0x03, 0x4b, 0x61, 0x73, 0xca, 0x02, 0x03, 0x4b, 0x61, 0x73, 0xe2, 0x02, - 0x0f, 0x4b, 0x61, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x03, 0x4b, 0x61, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x90, 0x02, 0x01, 0x12, 0x78, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4c, 0x65, 0x67, + 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x2a, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x6b, 0x61, 0x73, 0x5f, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x90, 0x02, 0x01, 0x12, 0x58, 0x0a, + 0x06, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x12, 0x12, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, + 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6b, 0x61, + 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x25, 0x92, 0x41, 0x09, 0x4a, 0x07, 0x0a, 0x03, 0x32, 0x30, 0x30, 0x12, 0x00, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x6b, 0x61, 0x73, 0x2f, 0x76, 0x32, + 0x2f, 0x72, 0x65, 0x77, 0x72, 0x61, 0x70, 0x42, 0xe2, 0x01, 0x92, 0x41, 0x73, 0x12, 0x71, 0x0a, + 0x1a, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x44, 0x46, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2a, 0x4c, 0x0a, 0x12, 0x42, + 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x43, 0x6c, 0x65, 0x61, + 0x72, 0x12, 0x36, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x62, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, + 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x05, 0x31, 0x2e, 0x35, 0x2e, 0x30, + 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x2e, 0x6b, 0x61, 0x73, 0x42, 0x08, 0x4b, 0x61, 0x73, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, + 0x61, 0x73, 0xa2, 0x02, 0x03, 0x4b, 0x58, 0x58, 0xaa, 0x02, 0x03, 0x4b, 0x61, 0x73, 0xca, 0x02, + 0x03, 0x4b, 0x61, 0x73, 0xe2, 0x02, 0x0f, 0x4b, 0x61, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x03, 0x4b, 0x61, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/kas/kasconnect/kas.connect.go b/protocol/go/kas/kasconnect/kas.connect.go index 7af392004f..fb443bfd92 100644 --- a/protocol/go/kas/kasconnect/kas.connect.go +++ b/protocol/go/kas/kasconnect/kas.connect.go @@ -73,12 +73,14 @@ func NewAccessServiceClient(httpClient connect.HTTPClient, baseURL string, opts httpClient, baseURL+AccessServicePublicKeyProcedure, connect.WithSchema(accessServicePublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), legacyPublicKey: connect.NewClient[kas.LegacyPublicKeyRequest, wrapperspb.StringValue]( httpClient, baseURL+AccessServiceLegacyPublicKeyProcedure, connect.WithSchema(accessServiceLegacyPublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), rewrap: connect.NewClient[kas.RewrapRequest, kas.RewrapResponse]( @@ -130,12 +132,14 @@ func NewAccessServiceHandler(svc AccessServiceHandler, opts ...connect.HandlerOp AccessServicePublicKeyProcedure, svc.PublicKey, connect.WithSchema(accessServicePublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) accessServiceLegacyPublicKeyHandler := connect.NewUnaryHandler( AccessServiceLegacyPublicKeyProcedure, svc.LegacyPublicKey, connect.WithSchema(accessServiceLegacyPublicKeyMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) accessServiceRewrapHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/attributes/attributes.pb.go b/protocol/go/policy/attributes/attributes.pb.go index 959297d557..818857614d 100644 --- a/protocol/go/policy/attributes/attributes.pb.go +++ b/protocol/go/policy/attributes/attributes.pb.go @@ -2094,176 +2094,177 @@ var file_policy_attributes_attributes_proto_rawDesc = []byte{ 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x32, 0xc1, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x72, 0x32, 0xcd, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x12, 0x92, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, - 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x79, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x12, 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, - 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x13, 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x66, 0x71, 0x6e, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, - 0x8e, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, - 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x91, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, + 0x74, 0x65, 0x73, 0x90, 0x02, 0x01, 0x12, 0x95, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, + 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x90, 0x02, 0x01, 0x12, 0x7c, + 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0xa1, 0x01, 0x0a, + 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, + 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, - 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, - 0x2a, 0x32, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, - 0x18, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x66, 0x71, 0x6e, 0x90, 0x02, 0x01, + 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8e, 0x01, 0x0a, 0x13, + 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x91, 0x01, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x32, 0x19, 0x2f, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, - 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, + 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xcd, 0x01, 0x0a, - 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, - 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xdb, 0x01, 0x0a, - 0x1c, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, - 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, - 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xc8, 0x01, 0x0a, 0x1e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, + 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xcd, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x2a, 0x29, 0x2f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, - 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, - 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, - 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, - 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, - 0x50, 0x41, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xdb, 0x01, 0x0a, 0x1c, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, 0x2f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, + 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xc8, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, + 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x2a, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x0f, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, + 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x41, 0x58, 0xaa, + 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x3a, 0x3a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/attributes/attributesconnect/attributes.connect.go b/protocol/go/policy/attributes/attributesconnect/attributes.connect.go index bcb8fb964d..ba84fcead3 100644 --- a/protocol/go/policy/attributes/attributesconnect/attributes.connect.go +++ b/protocol/go/policy/attributes/attributesconnect/attributes.connect.go @@ -142,24 +142,28 @@ func NewAttributesServiceClient(httpClient connect.HTTPClient, baseURL string, o httpClient, baseURL+AttributesServiceListAttributesProcedure, connect.WithSchema(attributesServiceListAttributesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), listAttributeValues: connect.NewClient[attributes.ListAttributeValuesRequest, attributes.ListAttributeValuesResponse]( httpClient, baseURL+AttributesServiceListAttributeValuesProcedure, connect.WithSchema(attributesServiceListAttributeValuesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getAttribute: connect.NewClient[attributes.GetAttributeRequest, attributes.GetAttributeResponse]( httpClient, baseURL+AttributesServiceGetAttributeProcedure, connect.WithSchema(attributesServiceGetAttributeMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getAttributeValuesByFqns: connect.NewClient[attributes.GetAttributeValuesByFqnsRequest, attributes.GetAttributeValuesByFqnsResponse]( httpClient, baseURL+AttributesServiceGetAttributeValuesByFqnsProcedure, connect.WithSchema(attributesServiceGetAttributeValuesByFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createAttribute: connect.NewClient[attributes.CreateAttributeRequest, attributes.CreateAttributeResponse]( @@ -367,24 +371,28 @@ func NewAttributesServiceHandler(svc AttributesServiceHandler, opts ...connect.H AttributesServiceListAttributesProcedure, svc.ListAttributes, connect.WithSchema(attributesServiceListAttributesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceListAttributeValuesHandler := connect.NewUnaryHandler( AttributesServiceListAttributeValuesProcedure, svc.ListAttributeValues, connect.WithSchema(attributesServiceListAttributeValuesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceGetAttributeHandler := connect.NewUnaryHandler( AttributesServiceGetAttributeProcedure, svc.GetAttribute, connect.WithSchema(attributesServiceGetAttributeMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceGetAttributeValuesByFqnsHandler := connect.NewUnaryHandler( AttributesServiceGetAttributeValuesByFqnsProcedure, svc.GetAttributeValuesByFqns, connect.WithSchema(attributesServiceGetAttributeValuesByFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) attributesServiceCreateAttributeHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go b/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go index 3cfc542bcb..ca127cf8a6 100644 --- a/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go +++ b/protocol/go/policy/kasregistry/kasregistryconnect/key_access_server_registry.connect.go @@ -91,12 +91,14 @@ func NewKeyAccessServerRegistryServiceClient(httpClient connect.HTTPClient, base httpClient, baseURL+KeyAccessServerRegistryServiceListKeyAccessServersProcedure, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServersMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getKeyAccessServer: connect.NewClient[kasregistry.GetKeyAccessServerRequest, kasregistry.GetKeyAccessServerResponse]( httpClient, baseURL+KeyAccessServerRegistryServiceGetKeyAccessServerProcedure, connect.WithSchema(keyAccessServerRegistryServiceGetKeyAccessServerMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createKeyAccessServer: connect.NewClient[kasregistry.CreateKeyAccessServerRequest, kasregistry.CreateKeyAccessServerResponse]( @@ -121,6 +123,7 @@ func NewKeyAccessServerRegistryServiceClient(httpClient connect.HTTPClient, base httpClient, baseURL+KeyAccessServerRegistryServiceListKeyAccessServerGrantsProcedure, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServerGrantsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), } @@ -192,12 +195,14 @@ func NewKeyAccessServerRegistryServiceHandler(svc KeyAccessServerRegistryService KeyAccessServerRegistryServiceListKeyAccessServersProcedure, svc.ListKeyAccessServers, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServersMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) keyAccessServerRegistryServiceGetKeyAccessServerHandler := connect.NewUnaryHandler( KeyAccessServerRegistryServiceGetKeyAccessServerProcedure, svc.GetKeyAccessServer, connect.WithSchema(keyAccessServerRegistryServiceGetKeyAccessServerMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) keyAccessServerRegistryServiceCreateKeyAccessServerHandler := connect.NewUnaryHandler( @@ -222,6 +227,7 @@ func NewKeyAccessServerRegistryServiceHandler(svc KeyAccessServerRegistryService KeyAccessServerRegistryServiceListKeyAccessServerGrantsProcedure, svc.ListKeyAccessServerGrants, connect.WithSchema(keyAccessServerRegistryServiceListKeyAccessServerGrantsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) return "/policy.kasregistry.KeyAccessServerRegistryService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go index 0a9200e734..3700049e57 100644 --- a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go +++ b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go @@ -1101,9 +1101,9 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x6e, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, - 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xe4, 0x07, 0x0a, 0x1e, 0x4b, 0x65, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xed, 0x07, 0x0a, 0x1e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x96, 0x01, 0x0a, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x99, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, @@ -1111,74 +1111,74 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, - 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, - 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, + 0x72, 0x76, 0x65, 0x72, 0x73, 0x90, 0x02, 0x01, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, + 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x9e, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, + 0x90, 0x02, 0x01, 0x12, 0x9c, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, + 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0xac, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, - 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, + 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, 0x2f, 0x6b, + 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, + 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaf, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, - 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, - 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, - 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, 0x65, 0x79, + 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x90, 0x02, 0x01, 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/namespaces/namespaces.pb.go b/protocol/go/policy/namespaces/namespaces.pb.go index e942ccd79a..7e77fce392 100644 --- a/protocol/go/policy/namespaces/namespaces.pb.go +++ b/protocol/go/policy/namespaces/namespaces.pb.go @@ -930,95 +930,96 @@ var file_policy_namespaces_namespaces_proto_rawDesc = []byte{ 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xab, 0x09, 0x0a, 0x10, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xb1, 0x09, 0x0a, 0x10, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x84, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x12, 0x87, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x74, 0x74, + 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, - 0x8b, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x90, 0x01, - 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, - 0x3a, 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x99, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, - 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xef, 0x01, 0x0a, - 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0x88, 0x01, 0x0a, 0x0e, 0x4c, + 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x4c, 0x3a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, - 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xd8, - 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, - 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, - 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x2a, 0x2d, 0x2f, 0x61, 0x74, 0x74, + 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, - 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x42, 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0xa2, 0x02, 0x03, 0x50, 0x4e, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xe2, - 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x90, 0x02, 0x01, 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x73, 0x12, 0x90, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x99, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x12, 0xef, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4c, 0x3a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, + 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x12, 0xd8, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, + 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, + 0x2a, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, + 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x42, 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, + 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x4e, 0x58, 0xaa, 0x02, 0x11, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go b/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go index 8df0903b60..a106981409 100644 --- a/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go +++ b/protocol/go/policy/namespaces/namespacesconnect/namespaces.connect.go @@ -96,12 +96,14 @@ func NewNamespaceServiceClient(httpClient connect.HTTPClient, baseURL string, op httpClient, baseURL+NamespaceServiceGetNamespaceProcedure, connect.WithSchema(namespaceServiceGetNamespaceMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), listNamespaces: connect.NewClient[namespaces.ListNamespacesRequest, namespaces.ListNamespacesResponse]( httpClient, baseURL+NamespaceServiceListNamespacesProcedure, connect.WithSchema(namespaceServiceListNamespacesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createNamespace: connect.NewClient[namespaces.CreateNamespaceRequest, namespaces.CreateNamespaceResponse]( @@ -209,12 +211,14 @@ func NewNamespaceServiceHandler(svc NamespaceServiceHandler, opts ...connect.Han NamespaceServiceGetNamespaceProcedure, svc.GetNamespace, connect.WithSchema(namespaceServiceGetNamespaceMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) namespaceServiceListNamespacesHandler := connect.NewUnaryHandler( NamespaceServiceListNamespacesProcedure, svc.ListNamespaces, connect.WithSchema(namespaceServiceListNamespacesMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) namespaceServiceCreateNamespaceHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/resourcemapping/resource_mapping.pb.go b/protocol/go/policy/resourcemapping/resource_mapping.pb.go index 4a1916bd2f..8740406745 100644 --- a/protocol/go/policy/resourcemapping/resource_mapping.pb.go +++ b/protocol/go/policy/resourcemapping/resource_mapping.pb.go @@ -1600,9 +1600,9 @@ var file_policy_resourcemapping_resource_mapping_proto_rawDesc = []byte{ 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x32, 0xbd, 0x0f, 0x0a, 0x16, 0x52, 0x65, + 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x32, 0xcc, 0x0f, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0xb2, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x76, 0x69, 0x63, 0x65, 0x12, 0xb5, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, @@ -1611,135 +1611,136 @@ var file_policy_resourcemapping_resource_mapping_proto_rawDesc = []byte{ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0xb1, 0x01, 0x0a, 0x17, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb8, 0x01, - 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0xbd, 0x01, 0x0a, 0x1a, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x32, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xba, 0x01, 0x0a, 0x1a, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x90, 0x02, 0x01, 0x12, 0xb4, 0x01, 0x0a, + 0x17, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1f, 0x12, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x90, 0x02, 0x01, 0x12, 0xb8, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x12, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x2a, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x33, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x14, 0x12, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xc9, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x79, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, 0x6e, 0x73, 0x12, 0x3e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0xbd, + 0x01, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x32, + 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x2d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xba, + 0x01, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x39, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x2a, 0x1d, 0x2f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2d, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa0, 0x01, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x90, 0x02, 0x01, 0x12, 0xcc, + 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x6e, 0x73, 0x12, 0x3e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, + 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, + 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x66, 0x71, 0x6e, 0x73, 0x90, 0x02, 0x01, 0x12, 0x9f, 0x01, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, + 0xa3, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x71, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2d, 0x66, 0x71, 0x6e, - 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, + 0x2a, 0x22, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa8, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, + 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x32, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0xa3, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x12, 0xa5, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, - 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa8, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x32, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, - 0x2a, 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xeb, 0x01, 0x0a, 0x1a, 0x63, 0x6f, - 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, - 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0xa2, 0x02, 0x03, 0x50, 0x52, 0x58, 0xaa, 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xca, - 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x22, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, + 0x17, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xeb, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, + 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xa2, + 0x02, 0x03, 0x50, 0x52, 0x58, 0xaa, 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xca, 0x02, + 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x22, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go b/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go index 415ba7fa15..c5589908e9 100644 --- a/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go +++ b/protocol/go/policy/resourcemapping/resourcemappingconnect/resource_mapping.connect.go @@ -115,12 +115,14 @@ func NewResourceMappingServiceClient(httpClient connect.HTTPClient, baseURL stri httpClient, baseURL+ResourceMappingServiceListResourceMappingGroupsProcedure, connect.WithSchema(resourceMappingServiceListResourceMappingGroupsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getResourceMappingGroup: connect.NewClient[resourcemapping.GetResourceMappingGroupRequest, resourcemapping.GetResourceMappingGroupResponse]( httpClient, baseURL+ResourceMappingServiceGetResourceMappingGroupProcedure, connect.WithSchema(resourceMappingServiceGetResourceMappingGroupMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createResourceMappingGroup: connect.NewClient[resourcemapping.CreateResourceMappingGroupRequest, resourcemapping.CreateResourceMappingGroupResponse]( @@ -145,18 +147,21 @@ func NewResourceMappingServiceClient(httpClient connect.HTTPClient, baseURL stri httpClient, baseURL+ResourceMappingServiceListResourceMappingsProcedure, connect.WithSchema(resourceMappingServiceListResourceMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), listResourceMappingsByGroupFqns: connect.NewClient[resourcemapping.ListResourceMappingsByGroupFqnsRequest, resourcemapping.ListResourceMappingsByGroupFqnsResponse]( httpClient, baseURL+ResourceMappingServiceListResourceMappingsByGroupFqnsProcedure, connect.WithSchema(resourceMappingServiceListResourceMappingsByGroupFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getResourceMapping: connect.NewClient[resourcemapping.GetResourceMappingRequest, resourcemapping.GetResourceMappingResponse]( httpClient, baseURL+ResourceMappingServiceGetResourceMappingProcedure, connect.WithSchema(resourceMappingServiceGetResourceMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createResourceMapping: connect.NewClient[resourcemapping.CreateResourceMappingRequest, resourcemapping.CreateResourceMappingResponse]( @@ -282,12 +287,14 @@ func NewResourceMappingServiceHandler(svc ResourceMappingServiceHandler, opts .. ResourceMappingServiceListResourceMappingGroupsProcedure, svc.ListResourceMappingGroups, connect.WithSchema(resourceMappingServiceListResourceMappingGroupsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceGetResourceMappingGroupHandler := connect.NewUnaryHandler( ResourceMappingServiceGetResourceMappingGroupProcedure, svc.GetResourceMappingGroup, connect.WithSchema(resourceMappingServiceGetResourceMappingGroupMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceCreateResourceMappingGroupHandler := connect.NewUnaryHandler( @@ -312,18 +319,21 @@ func NewResourceMappingServiceHandler(svc ResourceMappingServiceHandler, opts .. ResourceMappingServiceListResourceMappingsProcedure, svc.ListResourceMappings, connect.WithSchema(resourceMappingServiceListResourceMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceListResourceMappingsByGroupFqnsHandler := connect.NewUnaryHandler( ResourceMappingServiceListResourceMappingsByGroupFqnsProcedure, svc.ListResourceMappingsByGroupFqns, connect.WithSchema(resourceMappingServiceListResourceMappingsByGroupFqnsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceGetResourceMappingHandler := connect.NewUnaryHandler( ResourceMappingServiceGetResourceMappingProcedure, svc.GetResourceMapping, connect.WithSchema(resourceMappingServiceGetResourceMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) resourceMappingServiceCreateResourceMappingHandler := connect.NewUnaryHandler( diff --git a/protocol/go/policy/subjectmapping/subject_mapping.pb.go b/protocol/go/policy/subjectmapping/subject_mapping.pb.go index 978ca54b47..e0653a135a 100644 --- a/protocol/go/policy/subjectmapping/subject_mapping.pb.go +++ b/protocol/go/policy/subjectmapping/subject_mapping.pb.go @@ -1589,7 +1589,7 @@ var file_policy_subjectmapping_subject_mapping_proto_rawDesc = []byte{ 0x1b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x14, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, - 0x74, 0x73, 0x32, 0xca, 0x10, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, + 0x74, 0x73, 0x32, 0xd6, 0x10, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb4, 0x01, 0x0a, 0x14, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, @@ -1602,7 +1602,7 @@ var file_policy_subjectmapping_subject_mapping_proto_rawDesc = []byte{ 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x12, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x74, 0x63, 0x68, 0x12, 0x9a, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, @@ -1610,133 +1610,134 @@ var file_policy_subjectmapping_subject_mapping_proto_rawDesc = []byte{ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x96, 0x01, - 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, - 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, - 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, - 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa2, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, - 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, - 0x3a, 0x01, 0x2a, 0x32, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9f, 0x01, 0x0a, 0x14, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xac, 0x01, - 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x12, 0xab, 0x01, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x90, 0x02, 0x01, + 0x12, 0x99, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb2, 0x01, 0x0a, 0x19, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x18, 0x12, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0x9d, 0x01, 0x0a, + 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xa2, 0x01, 0x0a, + 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x32, 0x16, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, + 0x7d, 0x12, 0x9f, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0xaf, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, + 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, 0x22, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x12, - 0xb7, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, + 0x74, 0x73, 0x90, 0x02, 0x01, 0x12, 0xae, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, + 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, + 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0xb2, 0x01, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x32, 0x1c, 0x2f, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, - 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x19, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0xdc, 0x01, 0x0a, 0x25, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, - 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x12, 0x43, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x44, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, - 0x6c, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x2a, 0x20, 0x2f, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x42, - 0xe4, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x13, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, - 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x03, 0x50, 0x53, 0x58, 0xaa, 0x02, 0x15, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0xca, 0x02, 0x15, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x53, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x21, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x5c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, + 0x01, 0x2a, 0x22, 0x17, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x12, 0xb7, 0x01, 0x0a, 0x19, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x32, 0x1c, 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, + 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xb4, 0x01, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x74, 0x12, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a, 0x1c, + 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xdc, 0x01, 0x0a, + 0x25, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, + 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x12, 0x43, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x6d, + 0x61, 0x70, 0x70, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x2a, 0x20, 0x2f, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x65, + 0x74, 0x73, 0x2f, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x42, 0xe4, 0x01, 0x0a, 0x19, + 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x73, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x42, 0x13, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, + 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xa2, + 0x02, 0x03, 0x50, 0x53, 0x58, 0xaa, 0x02, 0x15, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x15, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x21, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x3a, 0x3a, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go b/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go index ddce801411..a4ca383de9 100644 --- a/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go +++ b/protocol/go/policy/subjectmapping/subjectmappingconnect/subject_mapping.connect.go @@ -127,12 +127,14 @@ func NewSubjectMappingServiceClient(httpClient connect.HTTPClient, baseURL strin httpClient, baseURL+SubjectMappingServiceListSubjectMappingsProcedure, connect.WithSchema(subjectMappingServiceListSubjectMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getSubjectMapping: connect.NewClient[subjectmapping.GetSubjectMappingRequest, subjectmapping.GetSubjectMappingResponse]( httpClient, baseURL+SubjectMappingServiceGetSubjectMappingProcedure, connect.WithSchema(subjectMappingServiceGetSubjectMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createSubjectMapping: connect.NewClient[subjectmapping.CreateSubjectMappingRequest, subjectmapping.CreateSubjectMappingResponse]( @@ -157,12 +159,14 @@ func NewSubjectMappingServiceClient(httpClient connect.HTTPClient, baseURL strin httpClient, baseURL+SubjectMappingServiceListSubjectConditionSetsProcedure, connect.WithSchema(subjectMappingServiceListSubjectConditionSetsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), getSubjectConditionSet: connect.NewClient[subjectmapping.GetSubjectConditionSetRequest, subjectmapping.GetSubjectConditionSetResponse]( httpClient, baseURL+SubjectMappingServiceGetSubjectConditionSetProcedure, connect.WithSchema(subjectMappingServiceGetSubjectConditionSetMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), createSubjectConditionSet: connect.NewClient[subjectmapping.CreateSubjectConditionSetRequest, subjectmapping.CreateSubjectConditionSetResponse]( @@ -307,12 +311,14 @@ func NewSubjectMappingServiceHandler(svc SubjectMappingServiceHandler, opts ...c SubjectMappingServiceListSubjectMappingsProcedure, svc.ListSubjectMappings, connect.WithSchema(subjectMappingServiceListSubjectMappingsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceGetSubjectMappingHandler := connect.NewUnaryHandler( SubjectMappingServiceGetSubjectMappingProcedure, svc.GetSubjectMapping, connect.WithSchema(subjectMappingServiceGetSubjectMappingMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceCreateSubjectMappingHandler := connect.NewUnaryHandler( @@ -337,12 +343,14 @@ func NewSubjectMappingServiceHandler(svc SubjectMappingServiceHandler, opts ...c SubjectMappingServiceListSubjectConditionSetsProcedure, svc.ListSubjectConditionSets, connect.WithSchema(subjectMappingServiceListSubjectConditionSetsMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceGetSubjectConditionSetHandler := connect.NewUnaryHandler( SubjectMappingServiceGetSubjectConditionSetProcedure, svc.GetSubjectConditionSet, connect.WithSchema(subjectMappingServiceGetSubjectConditionSetMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) subjectMappingServiceCreateSubjectConditionSetHandler := connect.NewUnaryHandler( diff --git a/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go b/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go index 383c7df676..8933ce80a9 100644 --- a/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go +++ b/protocol/go/wellknownconfiguration/wellknown_configuration.pb.go @@ -187,8 +187,8 @@ var file_wellknownconfiguration_wellknown_configuration_proto_rawDesc = []byte{ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x32, 0xd1, 0x01, 0x0a, 0x10, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbc, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, + 0x69, 0x6f, 0x6e, 0x32, 0xd4, 0x01, 0x0a, 0x10, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, + 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbf, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, @@ -197,26 +197,26 @@ var file_wellknownconfiguration_wellknown_configuration_proto_rawDesc = []byte{ 0x1a, 0x39, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x2d, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0xf1, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, - 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x1b, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x77, - 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x57, 0x58, 0x58, 0xaa, 0x02, 0x16, 0x57, 0x65, - 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x22, - 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x90, 0x02, 0x01, 0x42, 0xf1, 0x01, 0x0a, 0x1a, 0x63, + 0x6f, 0x6d, 0x2e, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x1b, 0x57, 0x65, 0x6c, 0x6c, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, + 0x6f, 0x2f, 0x77, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x57, 0x58, 0x58, 0xaa, 0x02, + 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0xe2, 0x02, 0x22, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x57, 0x65, 0x6c, 0x6c, 0x6b, 0x6e, 0x6f, 0x77, + 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go b/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go index ac0b4ae299..35ce658693 100644 --- a/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go +++ b/protocol/go/wellknownconfiguration/wellknownconfigurationconnect/wellknown_configuration.connect.go @@ -63,6 +63,7 @@ func NewWellKnownServiceClient(httpClient connect.HTTPClient, baseURL string, op httpClient, baseURL+WellKnownServiceGetWellKnownConfigurationProcedure, connect.WithSchema(wellKnownServiceGetWellKnownConfigurationMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithClientOptions(opts...), ), } @@ -95,6 +96,7 @@ func NewWellKnownServiceHandler(svc WellKnownServiceHandler, opts ...connect.Han WellKnownServiceGetWellKnownConfigurationProcedure, svc.GetWellKnownConfiguration, connect.WithSchema(wellKnownServiceGetWellKnownConfigurationMethodDescriptor), + connect.WithIdempotency(connect.IdempotencyNoSideEffects), connect.WithHandlerOptions(opts...), ) return "/wellknownconfiguration.WellKnownService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/sdk/audit/context_keys.go b/sdk/audit/context_keys.go index 86104c0e93..149b4f1d4c 100644 --- a/sdk/audit/context_keys.go +++ b/sdk/audit/context_keys.go @@ -17,3 +17,7 @@ const ( RequestIPHeaderKey RequestHeader = "x-forwarded-request-ip" ActorIDHeaderKey RequestHeader = "x-forwarded-actor-id" ) + +func (r RequestHeader) String() string { + return string(r) +} diff --git a/service/authorization/authorization.go b/service/authorization/authorization.go index 8031fa7805..7112934443 100644 --- a/service/authorization/authorization.go +++ b/service/authorization/authorization.go @@ -8,15 +8,14 @@ import ( "os" "strings" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "connectrpc.com/connect" "github.com/creasty/defaults" "github.com/go-playground/validator/v10" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/mitchellh/mapstructure" "github.com/open-policy-agent/opa/rego" "github.com/opentdf/platform/protocol/go/authorization" + "github.com/opentdf/platform/protocol/go/authorization/authorizationconnect" "github.com/opentdf/platform/protocol/go/entityresolution" "github.com/opentdf/platform/protocol/go/policy" attr "github.com/opentdf/platform/protocol/go/policy/attributes" @@ -35,7 +34,6 @@ import ( const EntityIDPrefix string = "entity_idx_" type AuthorizationService struct { //nolint:revive // AuthorizationService is a valid name for this struct - authorization.UnimplementedAuthorizationServiceServer sdk *otdf.SDK config Config logger *logger.Logger @@ -54,12 +52,14 @@ type CustomRego struct { Query string `mapstructure:"query" json:"query" default:"data.opentdf.entitlements.attributes"` } -func NewRegistration() *serviceregistry.Service[AuthorizationService] { - return &serviceregistry.Service[AuthorizationService]{ - ServiceOptions: serviceregistry.ServiceOptions[AuthorizationService]{ - Namespace: "authorization", - ServiceDesc: &authorization.AuthorizationService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*AuthorizationService, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[authorizationconnect.AuthorizationServiceHandler] { + return &serviceregistry.Service[authorizationconnect.AuthorizationServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[authorizationconnect.AuthorizationServiceHandler]{ + Namespace: "authorization", + ServiceDesc: &authorization.AuthorizationService_ServiceDesc, + ConnectRPCFunc: authorizationconnect.NewAuthorizationServiceHandler, + GRPCGateayFunc: authorization.RegisterAuthorizationServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (authorizationconnect.AuthorizationServiceHandler, serviceregistry.HandlerServer) { var ( err error entitlementRego []byte @@ -134,9 +134,7 @@ func NewRegistration() *serviceregistry.Service[AuthorizationService] { as.config = *authZCfg - return as, func(ctx context.Context, mux *runtime.ServeMux) error { - return authorization.RegisterAuthorizationServiceHandlerServer(ctx, mux, as) - } + return as, nil }, }, } @@ -148,10 +146,10 @@ func (as AuthorizationService) IsReady(ctx context.Context) error { return nil } -func (as *AuthorizationService) GetDecisionsByToken(ctx context.Context, req *authorization.GetDecisionsByTokenRequest) (*authorization.GetDecisionsByTokenResponse, error) { +func (as *AuthorizationService) GetDecisionsByToken(ctx context.Context, req *connect.Request[authorization.GetDecisionsByTokenRequest]) (*connect.Response[authorization.GetDecisionsByTokenResponse], error) { decisionsRequests := []*authorization.DecisionRequest{} // for each token decision request - for _, tdr := range req.GetDecisionRequests() { + for _, tdr := range req.Msg.GetDecisionRequests() { ecResp, err := as.sdk.EntityResoution.CreateEntityChainFromJwt(ctx, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: tdr.GetTokens()}) if err != nil { as.logger.Error("Error calling ERS to get entity chains from jwts") @@ -166,23 +164,27 @@ func (as *AuthorizationService) GetDecisionsByToken(ctx context.Context, req *au }) } - resp, err := as.GetDecisions(ctx, &authorization.GetDecisionsRequest{ - DecisionRequests: decisionsRequests, + resp, err := as.GetDecisions(ctx, &connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: decisionsRequests, + }, }) if err != nil { return nil, err } - return &authorization.GetDecisionsByTokenResponse{DecisionResponses: resp.GetDecisionResponses()}, err + return connect.NewResponse(&authorization.GetDecisionsByTokenResponse{ + DecisionResponses: resp.Msg.GetDecisionResponses(), + }), err } -func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authorization.GetDecisionsRequest) (*authorization.GetDecisionsResponse, error) { +func (as *AuthorizationService) GetDecisions(ctx context.Context, req *connect.Request[authorization.GetDecisionsRequest]) (*connect.Response[authorization.GetDecisionsResponse], error) { as.logger.DebugContext(ctx, "getting decisions") // Temporary canned echo response with permit decision for all requested decision/entity/ra combos rsp := &authorization.GetDecisionsResponse{ DecisionResponses: make([]*authorization.DecisionResponse, 0), } - for _, dr := range req.GetDecisionRequests() { + for _, dr := range req.Msg.GetDecisionRequests() { for _, ra := range dr.GetResourceAttributes() { as.logger.DebugContext(ctx, "getting resource attributes", slog.String("FQNs", strings.Join(ra.GetAttributeValueFqns(), ", "))) @@ -226,7 +228,7 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza attrDefs, err = populateAttrDefValueFqns(attrDefs) if err != nil { - return nil, err + return nil, connect.NewError(connect.CodeInternal, err) } // get the relevant resource attribute fqns @@ -246,9 +248,11 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza // TODO: we should already have the subject mappings here and be able to just use OPA to trim down the known data attr values to the ones matched up with the entities // entities := ec.GetEntities() - req := authorization.GetEntitlementsRequest{ - Entities: entities, - Scope: &allPertinentFqnsRA, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: entities, + Scope: &allPertinentFqnsRA, + }, } auditECEntitlements := make([]audit.EntityChainEntitlement, 0) @@ -271,7 +275,7 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza // TODO this might cause errors if multiple entities dont have ids // currently just adding each entity returned to same list - for idx, e := range ecEntitlements.GetEntitlements() { + for idx, e := range ecEntitlements.Msg.GetEntitlements() { entityID := e.GetEntityId() if entityID == "" { entityID = EntityIDPrefix + fmt.Sprint(idx) @@ -357,7 +361,7 @@ func (as *AuthorizationService) GetDecisions(ctx context.Context, req *authoriza } } } - return rsp, nil + return connect.NewResponse(rsp), nil } // makeSubMapsByValLookup creates a lookup map of subject mappings by attribute value ID. @@ -438,20 +442,20 @@ func makeScopeMap(scope *authorization.ResourceAttribute) map[string]bool { return scopeMap } -func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *authorization.GetEntitlementsRequest) (*authorization.GetEntitlementsResponse, error) { +func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *connect.Request[authorization.GetEntitlementsRequest]) (*connect.Response[authorization.GetEntitlementsResponse], error) { as.logger.DebugContext(ctx, "getting entitlements") attrsRes, err := as.sdk.Attributes.ListAttributes(ctx, &attr.ListAttributesRequest{}) if err != nil { as.logger.ErrorContext(ctx, "failed to list attributes", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to list attributes") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to list attributes")) } subMapsRes, err := as.sdk.SubjectMapping.ListSubjectMappings(ctx, &subjectmapping.ListSubjectMappingsRequest{}) if err != nil { as.logger.ErrorContext(ctx, "failed to list subject mappings", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to list subject mappings") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to list subject mappings")) } // create a lookup map of attribute value FQNs (based on request scope) - scopeMap := makeScopeMap(req.GetScope()) + scopeMap := makeScopeMap(req.Msg.GetScope()) // create a lookup map of subject mappings by attribute value ID subMapsByVal := makeSubMapsByValLookup(subMapsRes.GetSubjectMappings()) // create a lookup map of attribute values by FQN (for rego query) @@ -462,18 +466,18 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author subjectMappings := avf.GetFqnAttributeValues() as.logger.DebugContext(ctx, fmt.Sprintf("retrieved %d subject mappings", len(subjectMappings))) // TODO: this could probably be moved to proto validation https://github.com/opentdf/platform/issues/1057 - if req.Entities == nil { + if req.Msg.Entities == nil { as.logger.ErrorContext(ctx, "requires entities") - return nil, status.Error(codes.InvalidArgument, "requires entities") + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("requires entities")) } rsp := &authorization.GetEntitlementsResponse{ - Entitlements: make([]*authorization.EntityEntitlements, len(req.GetEntities())), + Entitlements: make([]*authorization.EntityEntitlements, len(req.Msg.GetEntities())), } // call ERS on all entities - ersResp, err := as.sdk.EntityResoution.ResolveEntities(ctx, &entityresolution.ResolveEntitiesRequest{Entities: req.GetEntities()}) + ersResp, err := as.sdk.EntityResoution.ResolveEntities(ctx, &entityresolution.ResolveEntitiesRequest{Entities: req.Msg.GetEntities()}) if err != nil { - as.logger.ErrorContext(ctx, "error calling ERS to resolve entities", "entities", req.GetEntities()) + as.logger.ErrorContext(ctx, "error calling ERS to resolve entities", "entities", req.Msg.GetEntities()) return nil, err } @@ -481,40 +485,43 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author in, err := entitlements.OpaInput(subjectMappings, ersResp) if err != nil { as.logger.ErrorContext(ctx, "failed to build rego input", slog.String("error", err.Error())) - return nil, status.Error(codes.Internal, "failed to build rego input") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to build rego input")) } results, err := as.eval.Eval(ctx, rego.EvalInput(in), ) if err != nil { - return nil, status.Error(codes.Internal, "failed to evaluate entitlements policy") + return nil, connect.NewError(connect.CodeInternal, errors.New("failed to evaluate entitlements policy")) } + + resp := connect.NewResponse(rsp) + // If we get no results and no error then we assume that the entity is not entitled to anything if len(results) == 0 { as.logger.DebugContext(ctx, "no entitlement results") - return rsp, nil + return resp, nil } // I am not sure how we would end up with multiple results but lets return an empty entitlement set for now if len(results) > 1 { as.logger.WarnContext(ctx, "multiple entitlement results", slog.Any("results", results)) - return rsp, nil + return resp, nil } // If we get no expressions then we assume that the entity is not entitled to anything if len(results[0].Expressions) == 0 { as.logger.WarnContext(ctx, "no entitlement expressions", slog.Any("results", results)) - return rsp, nil + return resp, nil } resultsEntitlements, entitlementsMapOk := results[0].Expressions[0].Value.(map[string]interface{}) if !entitlementsMapOk { as.logger.ErrorContext(ctx, "entitlements is not a map[string]interface", slog.Any("value", resultsEntitlements)) - return rsp, nil + return resp, nil } as.logger.DebugContext(ctx, "rego results", slog.Any("results", results)) - for idx, entity := range req.GetEntities() { + for idx, entity := range req.Msg.GetEntities() { // Ensure the entity has an ID entityID := entity.GetId() if entityID == "" { @@ -524,7 +531,7 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author entityEntitlements, valueListOk := resultsEntitlements[entityID].([]interface{}) if !valueListOk { as.logger.ErrorContext(ctx, "entitlements is not a map[string]interface", slog.Any("value", resultsEntitlements)) - return rsp, nil + return resp, nil } // map for attributes for optional comprehensive @@ -541,20 +548,20 @@ func (as *AuthorizationService) GetEntitlements(ctx context.Context, req *author continue } // if comprehensive and a hierarchy attribute is entitled then add the lower entitlements - if req.GetWithComprehensiveHierarchy() { + if req.Msg.GetWithComprehensiveHierarchy() { entitlements = getComprehensiveHierarchy(attributesMap, avf, entitlement, as, entitlements) } // Add entitlement to entitlements array entitlements[valueIDX] = entitlement } // Update the entity with its entitlements - rsp.Entitlements[idx] = &authorization.EntityEntitlements{ + resp.Msg.Entitlements[idx] = &authorization.EntityEntitlements{ EntityId: entity.GetId(), AttributeValueFqns: entitlements, } } - return rsp, nil + return resp, nil } func retrieveAttributeDefinitions(ctx context.Context, ra *authorization.ResourceAttribute, sdk *otdf.SDK) (map[string]*attr.GetAttributeValuesByFqnsResponse_AttributeAndValue, error) { diff --git a/service/authorization/authorization_test.go b/service/authorization/authorization_test.go index 59940559fe..e64f849b78 100644 --- a/service/authorization/authorization_test.go +++ b/service/authorization/authorization_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "connectrpc.com/connect" "github.com/open-policy-agent/opa/rego" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" @@ -63,6 +64,7 @@ func (*mySubjectMappingClient) ListSubjectMappings(_ context.Context, _ *sm.List func (*myERSClient) CreateEntityChainFromJwt(_ context.Context, _ *entityresolution.CreateEntityChainFromJwtRequest, _ ...grpc.CallOption) (*entityresolution.CreateEntityChainFromJwtResponse, error) { return &createEntityChainResp, nil } + func (*myERSClient) ResolveEntities(_ context.Context, _ *entityresolution.ResolveEntitiesRequest, _ ...grpc.CallOption) (*entityresolution.ResolveEntitiesResponse, error) { return &resolveEntitiesResp, nil } @@ -177,13 +179,14 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -200,27 +203,34 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { require.NoError(t, err) // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, }, - }} + } - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -228,42 +238,46 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { assert.NotNil(t, resp) // one entitlement, one attribute value throughout - slog.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[0].GetDecision()) + slog.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[0].GetDecision()) // run again with two attribute values throughout // set the request - req = authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req = connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, - }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, - }, - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, - }, }, - }} + } attrDef.Values = append(attrDef.Values, &policy.Value{ Value: mockAttrValue2, }) @@ -288,9 +302,9 @@ func Test_GetDecisionsAllOf_Pass(t *testing.T) { resp, err = as.GetDecisions(ctxb, &req) require.NoError(t, err) - assert.Len(t, resp.GetDecisionResponses(), 2) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[0].GetDecision()) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[1].GetDecision()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 2) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[0].GetDecision()) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[1].GetDecision()) } func Test_GetDecisions_AllOf_Fail(t *testing.T) { @@ -331,32 +345,37 @@ func Test_GetDecisions_AllOf_Fail(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1, mockFqn2}}, - }, }, - }} + } ctxb := context.Background() @@ -371,10 +390,13 @@ func Test_GetDecisions_AllOf_Fail(t *testing.T) { prepared, err := testrego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -384,9 +406,9 @@ func Test_GetDecisions_AllOf_Fail(t *testing.T) { // NOTE: there should be two decision responses, one for each data attribute value, but authorization service // only responds with one permit/deny at the moment // entitlements only contain the first FQN, so we have a deny decision - as.logger.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.GetDecisionResponses()[0].GetDecision()) + as.logger.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.Msg.GetDecisionResponses()[0].GetDecision()) } // Subject entitled and environment entity not entitled -- still pass @@ -421,13 +443,14 @@ func Test_GetDecisionsAllOfWithEnvironmental_Pass(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -444,28 +467,35 @@ func Test_GetDecisionsAllOfWithEnvironmental_Pass(t *testing.T) { require.NoError(t, err) // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, - {Id: "e2", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, + {Id: "e2", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, }, - }} + } - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -473,9 +503,9 @@ func Test_GetDecisionsAllOfWithEnvironmental_Pass(t *testing.T) { assert.NotNil(t, resp) // one entitlement, one attribute value throughout - slog.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.GetDecisionResponses()[0].GetDecision()) + slog.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_PERMIT, resp.Msg.GetDecisionResponses()[0].GetDecision()) } // Subject not entitled and environment entity entitled -- still fail @@ -510,13 +540,14 @@ func Test_GetDecisionsAllOfWithEnvironmental_Fail(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -533,28 +564,35 @@ func Test_GetDecisionsAllOfWithEnvironmental_Fail(t *testing.T) { require.NoError(t, err) // set the request - req := authorization.GetDecisionsRequest{DecisionRequests: []*authorization.DecisionRequest{ - { - Actions: []*policy.Action{}, - EntityChains: []*authorization.EntityChain{ + req := connect.Request[authorization.GetDecisionsRequest]{ + Msg: &authorization.GetDecisionsRequest{ + DecisionRequests: []*authorization.DecisionRequest{ { - Id: "ec1", - Entities: []*authorization.Entity{ - {Id: "e2", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, - {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + Actions: []*policy.Action{}, + EntityChains: []*authorization.EntityChain{ + { + Id: "ec1", + Entities: []*authorization.Entity{ + {Id: "e2", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}, + {Id: "e1", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}, Category: authorization.Entity_CATEGORY_SUBJECT}, + }, + }, + }, + ResourceAttributes: []*authorization.ResourceAttribute{ + {AttributeValueFqns: []string{mockFqn1}}, }, }, }, - ResourceAttributes: []*authorization.ResourceAttribute{ - {AttributeValueFqns: []string{mockFqn1}}, - }, }, - }} + } - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } resp, err := as.GetDecisions(ctxb, &req) @@ -562,9 +600,9 @@ func Test_GetDecisionsAllOfWithEnvironmental_Fail(t *testing.T) { assert.NotNil(t, resp) // one entitlement, one attribute value throughout - slog.Debug(resp.String()) - assert.Len(t, resp.GetDecisionResponses(), 1) - assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.GetDecisionResponses()[0].GetDecision()) + slog.Debug(resp.Msg.String()) + assert.Len(t, resp.Msg.GetDecisionResponses(), 1) + assert.Equal(t, authorization.DecisionResponse_DECISION_DENY, resp.Msg.GetDecisionResponses()[0].GetDecision()) } func Test_GetEntitlementsSimple(t *testing.T) { @@ -600,13 +638,14 @@ func Test_GetEntitlementsSimple(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -622,23 +661,28 @@ func Test_GetEntitlementsSimple(t *testing.T) { prepared, err := rego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } - req := authorization.GetEntitlementsRequest{ - Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, - Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, + Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, + }, } resp, err := as.GetEntitlements(ctxb, &req) require.NoError(t, err) assert.NotNil(t, resp) - assert.Len(t, resp.GetEntitlements(), 1) - assert.Equal(t, "e1", resp.GetEntitlements()[0].GetEntityId()) - assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.GetEntitlements()[0].GetAttributeValueFqns()) + assert.Len(t, resp.Msg.GetEntitlements(), 1) + assert.Equal(t, "e1", resp.Msg.GetEntitlements()[0].GetEntityId()) + assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.Msg.GetEntitlements()[0].GetAttributeValueFqns()) } func Test_GetEntitlementsFqnCasing(t *testing.T) { @@ -667,13 +711,14 @@ func Test_GetEntitlementsFqnCasing(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -689,18 +734,23 @@ func Test_GetEntitlementsFqnCasing(t *testing.T) { prepared, err := rego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } - req := authorization.GetEntitlementsRequest{ - Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, - // Using mixed case here - Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/VaLuE1"}}, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, + // Using mixed case here + Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/VaLuE1"}}, + }, } - for fqn := range makeScopeMap(req.GetScope()) { + for fqn := range makeScopeMap(req.Msg.GetScope()) { assert.Equal(t, fqn, strings.ToLower(fqn)) } @@ -708,9 +758,9 @@ func Test_GetEntitlementsFqnCasing(t *testing.T) { require.NoError(t, err) assert.NotNil(t, resp) - assert.Len(t, resp.GetEntitlements(), 1) - assert.Equal(t, "e1", resp.GetEntitlements()[0].GetEntityId()) - assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.GetEntitlements()[0].GetAttributeValueFqns()) + assert.Len(t, resp.Msg.GetEntitlements(), 1) + assert.Equal(t, "e1", resp.Msg.GetEntitlements()[0].GetEntityId()) + assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1"}, resp.Msg.GetEntitlements()[0].GetAttributeValueFqns()) } func Test_GetEntitlementsWithComprehensiveHierarchy(t *testing.T) { @@ -747,13 +797,14 @@ func Test_GetEntitlementsWithComprehensiveHierarchy(t *testing.T) { } userStruct, _ := structpb.NewStruct(userRepresentation) resolveEntitiesResp = entityresolution.ResolveEntitiesResponse{ - EntityRepresentations: []*entityresolution.EntityRepresentation{{ - OriginalId: "e1", - AdditionalProps: []*structpb.Struct{ - userStruct, + EntityRepresentations: []*entityresolution.EntityRepresentation{ + { + OriginalId: "e1", + AdditionalProps: []*structpb.Struct{ + userStruct, + }, }, }, - }, } ctxb := context.Background() @@ -768,25 +819,30 @@ func Test_GetEntitlementsWithComprehensiveHierarchy(t *testing.T) { // Run evaluation. prepared, err := rego.PrepareForEval(ctxb) require.NoError(t, err) - as := AuthorizationService{logger: logger, sdk: &otdf.SDK{ - SubjectMapping: &mySubjectMappingClient{}, - Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}}, - eval: prepared} + as := AuthorizationService{ + logger: logger, sdk: &otdf.SDK{ + SubjectMapping: &mySubjectMappingClient{}, + Attributes: &myAttributesClient{}, EntityResoution: &myERSClient{}, + }, + eval: prepared, + } withHierarchy := true - req := authorization.GetEntitlementsRequest{ - Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, - Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, - WithComprehensiveHierarchy: &withHierarchy, + req := connect.Request[authorization.GetEntitlementsRequest]{ + Msg: &authorization.GetEntitlementsRequest{ + Entities: []*authorization.Entity{{Id: "e1", EntityType: &authorization.Entity_ClientId{ClientId: "testclient"}, Category: authorization.Entity_CATEGORY_ENVIRONMENT}}, + Scope: &authorization.ResourceAttribute{AttributeValueFqns: []string{"https://www.example.org/attr/foo/value/value1"}}, + WithComprehensiveHierarchy: &withHierarchy, + }, } resp, err := as.GetEntitlements(ctxb, &req) require.NoError(t, err) assert.NotNil(t, resp) - assert.Len(t, resp.GetEntitlements(), 1) - assert.Equal(t, "e1", resp.GetEntitlements()[0].GetEntityId()) - assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1", "https://www.example.org/attr/foo/value/value2"}, resp.GetEntitlements()[0].GetAttributeValueFqns()) + assert.Len(t, resp.Msg.GetEntitlements(), 1) + assert.Equal(t, "e1", resp.Msg.GetEntitlements()[0].GetEntityId()) + assert.Equal(t, []string{"https://www.example.org/attr/foo/value/value1", "https://www.example.org/attr/foo/value/value2"}, resp.Msg.GetEntitlements()[0].GetAttributeValueFqns()) } func TestFqnBuilder(t *testing.T) { diff --git a/service/entityresolution/claims/claims_entity_resolution.go b/service/entityresolution/claims/claims_entity_resolution.go index 07ca34fd4a..090d2b676c 100644 --- a/service/entityresolution/claims/claims_entity_resolution.go +++ b/service/entityresolution/claims/claims_entity_resolution.go @@ -5,7 +5,7 @@ import ( "fmt" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" @@ -24,20 +24,17 @@ type ClaimsEntityResolutionService struct { func RegisterClaimsERS(_ serviceregistry.ServiceConfig, logger *logger.Logger) (ClaimsEntityResolutionService, serviceregistry.HandlerServer) { claimsSVC := ClaimsEntityResolutionService{logger: logger} - return claimsSVC, - func(ctx context.Context, mux *runtime.ServeMux) error { - return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, claimsSVC) - } + return claimsSVC, nil } -func (s ClaimsEntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { - resp, err := EntityResolution(ctx, req, s.logger) - return &resp, err +func (s ClaimsEntityResolutionService) ResolveEntities(ctx context.Context, req *connect.Request[entityresolution.ResolveEntitiesRequest]) (*connect.Response[entityresolution.ResolveEntitiesResponse], error) { + resp, err := EntityResolution(ctx, req.Msg, s.logger) + return connect.NewResponse(&resp), err } -func (s ClaimsEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { - resp, err := CreateEntityChainFromJwt(ctx, req, s.logger) - return &resp, err +func (s ClaimsEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *connect.Request[entityresolution.CreateEntityChainFromJwtRequest]) (*connect.Response[entityresolution.CreateEntityChainFromJwtResponse], error) { + resp, err := CreateEntityChainFromJwt(ctx, req.Msg, s.logger) + return connect.NewResponse(&resp), err } func CreateEntityChainFromJwt( @@ -72,14 +69,14 @@ func EntityResolution(_ context.Context, if claims != nil { err := claims.UnmarshalTo(entityStruct) if err != nil { - return entityresolution.ResolveEntitiesResponse{}, fmt.Errorf("error unpacking anypb.Any to structpb.Struct: %w", err) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("error unpacking anypb.Any to structpb.Struct: %w", err)) } } default: retrievedStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, fmt.Errorf("unable to make entity struct: %w", err) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, fmt.Errorf("unable to make entity struct: %w", err)) } entityStruct = retrievedStruct } diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index d66c2dc6b4..cd09205c00 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -3,6 +3,7 @@ package entityresolution import ( "github.com/mitchellh/mapstructure" "github.com/opentdf/platform/protocol/go/entityresolution" + "github.com/opentdf/platform/protocol/go/entityresolution/entityresolutionconnect" claims "github.com/opentdf/platform/service/entityresolution/claims" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak" "github.com/opentdf/platform/service/pkg/serviceregistry" @@ -18,15 +19,17 @@ const ( ) type EntityResolution struct { - entityresolution.EntityResolutionServiceServer + entityresolutionconnect.EntityResolutionServiceHandler } -func NewRegistration() *serviceregistry.Service[EntityResolution] { - return &serviceregistry.Service[EntityResolution]{ - ServiceOptions: serviceregistry.ServiceOptions[EntityResolution]{ - Namespace: "entityresolution", - ServiceDesc: &entityresolution.EntityResolutionService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*EntityResolution, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityResolutionServiceHandler] { + return &serviceregistry.Service[entityresolutionconnect.EntityResolutionServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[entityresolutionconnect.EntityResolutionServiceHandler]{ + Namespace: "entityresolution", + ServiceDesc: &entityresolution.EntityResolutionService_ServiceDesc, + ConnectRPCFunc: entityresolutionconnect.NewEntityResolutionServiceHandler, + GRPCGateayFunc: entityresolution.RegisterEntityResolutionServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (entityresolutionconnect.EntityResolutionServiceHandler, serviceregistry.HandlerServer) { var inputConfig ERSConfig if err := mapstructure.Decode(srp.Config, &inputConfig); err != nil { @@ -34,12 +37,12 @@ func NewRegistration() *serviceregistry.Service[EntityResolution] { } if inputConfig.Mode == ClaimsMode { claimsSVC, claimsHandler := claims.RegisterClaimsERS(srp.Config, srp.Logger) - return &EntityResolution{EntityResolutionServiceServer: claimsSVC}, claimsHandler + return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } // Default to keycloak ERS kcSVC, kcHandler := keycloak.RegisterKeycloakERS(srp.Config, srp.Logger) - return &EntityResolution{EntityResolutionServiceServer: kcSVC}, kcHandler + return EntityResolution{EntityResolutionServiceHandler: kcSVC}, kcHandler }, }, } diff --git a/service/entityresolution/keycloak/keycloak_entity_resolution.go b/service/entityresolution/keycloak/keycloak_entity_resolution.go index 16d3ba7e2b..14a5caf4e8 100644 --- a/service/entityresolution/keycloak/keycloak_entity_resolution.go +++ b/service/entityresolution/keycloak/keycloak_entity_resolution.go @@ -8,8 +8,8 @@ import ( "log/slog" "strings" + "connectrpc.com/connect" "github.com/Nerzal/gocloak/v13" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/mitchellh/mapstructure" "github.com/opentdf/platform/protocol/go/authorization" @@ -18,15 +18,14 @@ import ( "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" ) -const ( - ErrTextCreationFailed = "resource creation failed" - ErrTextGetRetrievalFailed = "resource retrieval failed" - ErrTextNotFound = "resource not found" +var ( + ErrCreationFailed = errors.New("resource creation failed") + ErrGetRetrievalFailed = errors.New("resource retrieval failed") + ErrNotFound = errors.New("resource not found") ) const ( @@ -59,20 +58,17 @@ func RegisterKeycloakERS(config serviceregistry.ServiceConfig, logger *logger.Lo } logger.Debug("entity_resolution configuration", "config", inputIdpConfig) keycloakSVC := &KeycloakEntityResolutionService{idpConfig: inputIdpConfig, logger: logger} - return keycloakSVC, - func(ctx context.Context, mux *runtime.ServeMux) error { - return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, keycloakSVC) - } + return keycloakSVC, nil } -func (s KeycloakEntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { - resp, err := EntityResolution(ctx, req, s.idpConfig, s.logger) - return &resp, err +func (s KeycloakEntityResolutionService) ResolveEntities(ctx context.Context, req *connect.Request[entityresolution.ResolveEntitiesRequest]) (*connect.Response[entityresolution.ResolveEntitiesResponse], error) { + resp, err := EntityResolution(ctx, req.Msg, s.idpConfig, s.logger) + return connect.NewResponse(&resp), err } -func (s KeycloakEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { - resp, err := CreateEntityChainFromJwt(ctx, req, s.idpConfig, s.logger) - return &resp, err +func (s KeycloakEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *connect.Request[entityresolution.CreateEntityChainFromJwtRequest]) (*connect.Response[entityresolution.CreateEntityChainFromJwtResponse], error) { + resp, err := CreateEntityChainFromJwt(ctx, req.Msg, s.idpConfig, s.logger) + return connect.NewResponse(&resp), err } func (c KeycloakConfig) LogValue() slog.Value { @@ -127,7 +123,7 @@ func EntityResolution(ctx context.Context, connector, err := getKCClient(ctx, kcConfig, logger) if err != nil { return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } payload := req.GetEntities() @@ -148,7 +144,7 @@ func EntityResolution(ctx context.Context, if err != nil { logger.Error("error getting client info", slog.String("error", err.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextGetRetrievalFailed) + connect.NewError(connect.CodeInternal, ErrGetRetrievalFailed) } var jsonEntities []*structpb.Struct for _, client := range clients { @@ -156,13 +152,13 @@ func EntityResolution(ctx context.Context, if err != nil { logger.Error("error serializing entity representation!", slog.String("error", err.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } mystruct, structErr := structpb.NewStruct(json) if structErr != nil { logger.Error("error making struct!", slog.String("error", structErr.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, mystruct) } @@ -171,7 +167,7 @@ func EntityResolution(ctx context.Context, entityStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Internal, ErrTextCreationFailed) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, entityStruct) } @@ -200,7 +196,7 @@ func EntityResolution(ctx context.Context, case err != nil: logger.Error(err.Error()) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextGetRetrievalFailed) + connect.NewError(connect.CodeInternal, ErrGetRetrievalFailed) case len(users) == 1: user := users[0] logger.Debug("user found", slog.String("user", *user.ID), slog.String("entity", ident.String())) @@ -221,14 +217,14 @@ func EntityResolution(ctx context.Context, case groupErr != nil: logger.Error("error getting group", slog.String("group", groupErr.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextGetRetrievalFailed) + connect.NewError(connect.CodeInternal, ErrGetRetrievalFailed) case len(groups) == 1: logger.Info("group found for", slog.String("entity", ident.String())) group := groups[0] expandedRepresentations, exErr := expandGroup(ctx, *group.ID, connector, &kcConfig, logger) if exErr != nil { return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextNotFound) + connect.NewError(connect.CodeNotFound, ErrNotFound) } else { keycloakEntities = expandedRepresentations } @@ -237,15 +233,15 @@ func EntityResolution(ctx context.Context, var entityNotFoundErr entityresolution.EntityNotFoundError switch ident.GetEntityType().(type) { case *authorization.Entity_EmailAddress: - entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.GetEmailAddress()} + entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(connect.CodeNotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.GetEmailAddress()} case *authorization.Entity_UserName: - entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.GetUserName()} + entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(connect.CodeNotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.GetUserName()} // case "": // return &entityresolution.IdpPluginResponse{}, // status.Error(codes.InvalidArgument, db.ErrTextNotFound) default: logger.Error("unsupported/unknown type for", slog.String("entity", ident.String())) - entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.String()} + entityNotFoundErr = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.String()} } logger.Error(entityNotFoundErr.String()) if kcConfig.InferID.From.Email || kcConfig.InferID.From.Username { @@ -253,11 +249,11 @@ func EntityResolution(ctx context.Context, entityStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct from email or username", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Internal, ErrTextCreationFailed) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, entityStruct) } else { - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Code(entityNotFoundErr.GetCode()), entityNotFoundErr.GetMessage()) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.Code(entityNotFoundErr.GetCode()), ErrGetRetrievalFailed) } } } else if ident.GetUserName() != "" { @@ -266,12 +262,12 @@ func EntityResolution(ctx context.Context, entityStruct, err := entityToStructPb(ident) if err != nil { logger.Error("unable to make entity struct from username", slog.String("error", err.Error())) - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Internal, ErrTextCreationFailed) + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, entityStruct) } else { - entityNotFoundErr := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrTextGetRetrievalFailed, Entity: ident.GetUserName()} - return entityresolution.ResolveEntitiesResponse{}, status.Error(codes.Code(entityNotFoundErr.GetCode()), entityNotFoundErr.GetMessage()) + entityNotFoundErr := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: ErrGetRetrievalFailed.Error(), Entity: ident.GetUserName()} + return entityresolution.ResolveEntitiesResponse{}, connect.NewError(connect.Code(entityNotFoundErr.GetCode()), ErrGetRetrievalFailed) } } } @@ -281,13 +277,13 @@ func EntityResolution(ctx context.Context, if err != nil { logger.Error("error serializing entity representation!", slog.String("error", err.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } mystruct, structErr := structpb.NewStruct(json) if structErr != nil { logger.Error("error making struct!", slog.String("error", structErr.Error())) return entityresolution.ResolveEntitiesResponse{}, - status.Error(codes.Internal, ErrTextCreationFailed) + connect.NewError(connect.CodeInternal, ErrCreationFailed) } jsonEntities = append(jsonEntities, mystruct) } diff --git a/service/entityresolution/keycloak/keycloak_entity_resolution_test.go b/service/entityresolution/keycloak/keycloak_entity_resolution_test.go index 4024e8cb44..b41d35bed9 100644 --- a/service/entityresolution/keycloak/keycloak_entity_resolution_test.go +++ b/service/entityresolution/keycloak/keycloak_entity_resolution_test.go @@ -10,6 +10,7 @@ import ( "strings" "testing" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak" @@ -17,7 +18,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) const tokenResp string = ` @@ -31,6 +31,7 @@ const byEmailBobResp = `[ {"id": "bobid", "username":"bob.smith"} ] ` + const byEmailAliceResp = `[ {"id": "aliceid", "username":"alice.smith"} ] @@ -48,27 +49,32 @@ const groupSubmemberResp = `[ {"id": "bobid", "username":"bob.smith"}, {"id": "aliceid", "username":"alice.smith"} ]` + const groupResp = `{ "id": "group1-uuid", "name": "group1" }` + const byClientIDOpentdfSdkResp = `[ {"id": "opentdfsdkclient", "clientId":"opentdf-sdk"} ] ` + const byClientIDTDFEntityResResp = `[ {"id": "tdf-entity-resolution", "clientId":"tdf-entity-resolution"} ] ` -const clientCredentialsJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE2MDQsImlhdCI6MTcxNTA5MTMwNCwianRpIjoiMTE3MTYzMjYtNWQyNS00MjlmLWFjMDItNmU0MjE2OWFjMGJhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiOTljOWVlZDItOTM1Ni00ZjE2LWIwODQtZTgyZDczZjViN2QyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxOTIuMTY4LjI0MC4xIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LXRkZi1lbnRpdHktcmVzb2x1dGlvbiIsImNsaWVudEFkZHJlc3MiOiIxOTIuMTY4LjI0MC4xIiwiY2xpZW50X2lkIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIn0.h29QLo-QvIc67KKqU_e1-x6G_o5YQccOyW9AthMdB7xhn9C1dBrcScytaWq1RfETPmnM8MXGezqN4OpXrYr-zbkHhq9ha0Ib-M1VJXNgA5sbgKW9JxGQyudmYPgn4fimDCJtAsXo7C-e3mYNm6DJS0zhGQ3msmjLTcHmIPzWlj7VjtPgKhYV75b7yr_yZNBdHjf3EZqfynU2sL8bKa1w7DYDNQve7ThtD4MeKLiuOQHa3_23dECs_ptvPVks7pLGgRKfgGHBC-KQuopjtxIhwkz2vOWRzugDl0aBJMHfwBajYhgZ2YRlV9dqSxmy8BOj4OEXuHbiyfIpY0rCRpSrGg" -const passwordPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0ODAsImlhdCI6MTcxNTA5MTE4MCwianRpIjoiZmI5MmM2MTAtYmI0OC00ZDgyLTljZGQtOWFhZjllNzEyNzc3IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uLXB1YmxpYyIsInNlc3Npb25fc3RhdGUiOiIzN2E3YjdiOS0xZmNlLTQxMmYtOTI1OS1lYzUxMTY3MGVhMGYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjM3YTdiN2I5LTFmY2UtNDEyZi05MjU5LWVjNTExNjcwZWEwZiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6InNhbXBsZSB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2FtcGxlLXVzZXIiLCJnaXZlbl9uYW1lIjoic2FtcGxlIiwiZmFtaWx5X25hbWUiOiJ1c2VyIiwiZW1haWwiOiJzYW1wbGV1c2VyQHNhbXBsZS5jb20ifQ.Gd_OvPNY7UfY7sBKh55TcvWQHmAkYZ2Jb2VyK1lYgse9EBEa_y3uoepZYrGMGkmYdwApg4eauQjxzT_BZYVBc7u9ch3HY_IUuSh3A6FkDDXZIziByP63FYiI4vKTp0w7e2-oYAdaUTDJ1Y50-l_VvRWjdc4fqi-OKH4t8D1rlq0GJ-P7uOl44Ta43YdBMuXI146-eLqx_zLIC49Pg5Y7MD_Lv23QfGTHTP47ckUQueXoGegNLQNE9nPTuD6lNzHD5_MOqse4IKzoWVs_hs4S8SqVxVlN_ZWXkcGhPllfQtf1qxLyFm51eYH3LGxqyNbGr4nQc8djPV0yWqOTrg8IYQ" -const passwordPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0MjMsImlhdCI6MTcxNTA5MTEyMywianRpIjoiMTNhNDljZmQtOGRiZC00NTA2LTk1NGMtZWFmZGRkNGE4ZTdjIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwic2Vzc2lvbl9zdGF0ZSI6ImNmZjYwZDZmLWI2M2MtNDBhYy1hYjI3LWFjZmU4MjY5OWQyYSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJjZmY2MGQ2Zi1iNjNjLTQwYWMtYWIyNy1hY2ZlODI2OTlkMmEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JFWKf7GZq1f8raP3Jm6rszpwPCh0JnaeZcHyC_AwcsNS6sJ9_qSY9wrbyHmvV9KIGMIPv23fymADZXb0ng7maeAv9NR34KiJqnKbmPeeWwL0cPoGOGOUICL6H5x1iTw7XaMDN2WQRrBRFuUkudybEF8n6fEGsAvcsXViaHjYwJyIEYCnHKPzuTvM1RjyGFsERpFXKls4UB_KhMBEonr4JOskupmX1pADBuicTNx_4whnd6ZDfiF5SSBohFV1ikwFOXK-qZ7znQfE-RJ-jV1CXBgEK8O66TMbMw9MbasS25xKoO0mH1_Ohf9niSXsY02o2qjGFZA9sWRk7K7pNgsxUw" -const authPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI2NDcsImlhdCI6MTcxNTA5MjM0NywiYXV0aF90aW1lIjoxNzE1MDkyMzQ3LCJqdGkiOiI3NzkwZmVhNC1hNzcyLTRhZTMtOTcyMi0yMTU2MmQyZGM5YmYiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImFmNmViOTRiLWU4ZDQtNDNlYi1hYzYwLTI3YmZiYjNiOTQxZSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiYWY2ZWI5NGItZThkNC00M2ViLWFjNjAtMjdiZmJiM2I5NDFlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.BfCX_fq2Q6cv5qb6TWzyCNiJf1vFw_iA4UTKr21ahUiNItNSW5ozET2jSLwKNAuMdBNrooU--OV1NniDcviIAMReaAEgjmAyBz6OSwAh3SmxzIU9Zy7f4V032FLDcVVoJ7CefItfBNu7WnWFGS7CYahNX_M2a6LXKhk7WRO4gQ2Ig11gtODlAP8jwLLAMU4_H9mVHD3LXd-IeOsnA8ZuBCq1DeFcn5T9tNZEGe0_21lp8spxoub0MRl-vYbgxEIoaeqxoSipb2hOjF7h0h1uaNhZT4m5ynHdd5yfspD8XjjjwlbXQn9Z8vrZUQQS6HLAi2pJIFNEoYxQk9lHal6VUA" -const authPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI3NDAsImlhdCI6MTcxNTA5MjQ0MCwiYXV0aF90aW1lIjoxNzE1MDkyNDQwLCJqdGkiOiIzZjk2ZDhjNC0yMjRkLTQyNjAtYmVkMy1lOGY2N2IwYTJjM2EiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiZDI1ZjhhZTMtYzE0Yy00ZWFmLTkzOWMtZjhlNGIyYmE1NDY3IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJkMjVmOGFlMy1jMTRjLTRlYWYtOTM5Yy1mOGU0YjJiYTU0NjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JphgIUbUeEEd25-Ji0o6_pcWvLzcQasCfr1z8WRt3xb1QrkN_d0_rmIpOJ9drhp8LjJPQRhFVxEU2TnAlYJ225IjPYolCrnEtKWsBbPJH9dP0cIJlilYplN4RZbmI9VbF578zAgVAs40n8aalNyxqYbPq_JViHDl_ufl4VEQ4Entzlp980I8whx3kfTygu0Yfl4eHLghPGt4LNPUmfeOIy8NKHbhmjHwKufrTmd0NV07cAOMUWl1NAF_4QWqmSqAY0SIcamwE7YlpuImzhj5PQH9tlyJMLr5m-k8CgKRfhpQ0H9cfVGUzWGG2A-lcNvxNmsk1kobmfHczjw13ajLKg" -const implicitPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTM4MzgsImlhdCI6MTcxNTA5MjkzOCwiYXV0aF90aW1lIjoxNzE1MDkyOTM4LCJqdGkiOiI0ZWIzY2I1OS05ZDRhLTQwNjctYmI0YS1iMjNjNDVhMDIyYTIiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiYmE1OWFmOTgtNmE3YS00YjRhLTliOTItODU1M2ZkM2EwMTNjIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJiYTU5YWY5OC02YTdhLTRiNGEtOWI5Mi04NTUzZmQzYTAxM2MiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.KQasyQ-f9KBRWRDXg4NikiHlragVil1nlYTQ8czPKku_uncpHZb7PMJhyPrwy72mwC10EJMpBIWGDVRfRjBRHxdzIbjozcGg3vusX748NMiDSlF4KoB5Fz-qExszcszEP5Qm_fvMRFcW7m9RPW9St1aaHcjAOW5Vee9ACJI56YffgqrTn1xp7ha2Z2X8d_NJfJOFdP3cqgxjR7DV5RezkDLRPfxHwJLk3anavSuDScXIO1w1C6AlTUQFVQUEX0DKZIt-RbzKcd6HWBfyDvHUSlfodEI_diWQIL1hEfrBXV6ThuhTqhrghHyIbb2e-zoC20arjMAK0Tr7hMAY4acxgQ" -const implicitPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUxNTE0MTMsImlhdCI6MTcxNTE1MDUxMywiYXV0aF90aW1lIjoxNzE1MTUwNTEzLCJqdGkiOiJlYTRmOGZiYS01ZjljLTRiMzQtYmU1ZC1jNTk2ZGI4YzNlYzkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImRlM2U2ZDc1LTI3ODItNDg4NS1iYzU4LTU0MmJmYzEzNWNkNSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiZGUzZTZkNzUtMjc4Mi00ODg1LWJjNTgtNTQyYmZjMTM1Y2Q1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.jH60V3ZkuiN6cuEmbRTspnxyOvQs_wNkgoBw9IEZ8E8yGzXDayouduxEd_O-DG6vjT4KPDxGC2lA0V4i-ke7KChkZhRYLkaSuqt2hTlKoLXotepJPq8GBlXhWjCmFMqaXEB8lMAlAEoCT7CWmg03eTBGzwynj0S4rjMuOj6TLf3HIIN0DP7bgtG9uIc0Ah_mTVJ4L6Y5yjv6LC9bMZ7YNpUIkFn-CZTudquxHkLYgxHgaRAfELBvmS5xn0pTrpIfZSdYQK7hGhjhm9fUg4J06Pg6QW-xZe1U7awyNl7pOeeGQ2lVTo1CWrAlOz9lAmzKzAwQakEOMXFxAjJeHsXTWg" -const tokenExchangeJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6ImE1NThkYzg0NzYzNDVjY2QyZWFhNjEzNjg4YmI2YTNkIn0.eyJleHAiOjE3MTU3OTA5MTAsImlhdCI6MTcxNTc5MDYxMCwianRpIjoiNjEyOTI2NzQtMDhmOS00ZmQ1LTk3Y2MtZDg3M2RhODRkZjllIiwiaXNzIjoiaHR0cHM6Ly9sb2NhbC1kc3AudmlydHJ1LmNvbTo4NDQzL2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwiYWNjb3VudCIsIm9wZW50ZGYtc2RrIl0sInN1YiI6ImU2ZWI0YWU1LThjMDUtNDI3NC04ZmExLTFmMGY1ZmJjY2JkZiIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZW50ZGYiLCJzZXNzaW9uX3N0YXRlIjoiZTQ0YzMxNWMtNjk5Yy00NGFkLTk2NDUtNmRkMmIyMjgzN2JlIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLXJlYWRvbmx5IiwiZGVmYXVsdC1yb2xlcy1vcGVudGRmIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJlNDRjMzE1Yy02OTljLTQ0YWQtOTY0NS02ZGQyYjIyODM3YmUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1vcGVudGRmLXNkayJ9.dmAulsUNfdPXVyWmVPsbGqaztshyHTD-m2hh1l2hmhwuNISJZjON0e1kXNxYXRLABr_PJzIpGYQCXz98yxOyiw" +const ( + clientCredentialsJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE2MDQsImlhdCI6MTcxNTA5MTMwNCwianRpIjoiMTE3MTYzMjYtNWQyNS00MjlmLWFjMDItNmU0MjE2OWFjMGJhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiOTljOWVlZDItOTM1Ni00ZjE2LWIwODQtZTgyZDczZjViN2QyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxOTIuMTY4LjI0MC4xIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LXRkZi1lbnRpdHktcmVzb2x1dGlvbiIsImNsaWVudEFkZHJlc3MiOiIxOTIuMTY4LjI0MC4xIiwiY2xpZW50X2lkIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIn0.h29QLo-QvIc67KKqU_e1-x6G_o5YQccOyW9AthMdB7xhn9C1dBrcScytaWq1RfETPmnM8MXGezqN4OpXrYr-zbkHhq9ha0Ib-M1VJXNgA5sbgKW9JxGQyudmYPgn4fimDCJtAsXo7C-e3mYNm6DJS0zhGQ3msmjLTcHmIPzWlj7VjtPgKhYV75b7yr_yZNBdHjf3EZqfynU2sL8bKa1w7DYDNQve7ThtD4MeKLiuOQHa3_23dECs_ptvPVks7pLGgRKfgGHBC-KQuopjtxIhwkz2vOWRzugDl0aBJMHfwBajYhgZ2YRlV9dqSxmy8BOj4OEXuHbiyfIpY0rCRpSrGg" + passwordPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0ODAsImlhdCI6MTcxNTA5MTE4MCwianRpIjoiZmI5MmM2MTAtYmI0OC00ZDgyLTljZGQtOWFhZjllNzEyNzc3IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uLXB1YmxpYyIsInNlc3Npb25fc3RhdGUiOiIzN2E3YjdiOS0xZmNlLTQxMmYtOTI1OS1lYzUxMTY3MGVhMGYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjM3YTdiN2I5LTFmY2UtNDEyZi05MjU5LWVjNTExNjcwZWEwZiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6InNhbXBsZSB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2FtcGxlLXVzZXIiLCJnaXZlbl9uYW1lIjoic2FtcGxlIiwiZmFtaWx5X25hbWUiOiJ1c2VyIiwiZW1haWwiOiJzYW1wbGV1c2VyQHNhbXBsZS5jb20ifQ.Gd_OvPNY7UfY7sBKh55TcvWQHmAkYZ2Jb2VyK1lYgse9EBEa_y3uoepZYrGMGkmYdwApg4eauQjxzT_BZYVBc7u9ch3HY_IUuSh3A6FkDDXZIziByP63FYiI4vKTp0w7e2-oYAdaUTDJ1Y50-l_VvRWjdc4fqi-OKH4t8D1rlq0GJ-P7uOl44Ta43YdBMuXI146-eLqx_zLIC49Pg5Y7MD_Lv23QfGTHTP47ckUQueXoGegNLQNE9nPTuD6lNzHD5_MOqse4IKzoWVs_hs4S8SqVxVlN_ZWXkcGhPllfQtf1qxLyFm51eYH3LGxqyNbGr4nQc8djPV0yWqOTrg8IYQ" + passwordPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTE0MjMsImlhdCI6MTcxNTA5MTEyMywianRpIjoiMTNhNDljZmQtOGRiZC00NTA2LTk1NGMtZWFmZGRkNGE4ZTdjIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4ODg4IiwicmVhbG0tbWFuYWdlbWVudCIsImFjY291bnQiXSwic3ViIjoiMmU2YzE1ODAtY2ZkMy00M2FiLWIxNzMtZjZjM2JmOGZmNGUyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGRmLWVudGl0eS1yZXNvbHV0aW9uIiwic2Vzc2lvbl9zdGF0ZSI6ImNmZjYwZDZmLWI2M2MtNDBhYy1hYjI3LWFjZmU4MjY5OWQyYSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiJjZmY2MGQ2Zi1iNjNjLTQwYWMtYWIyNy1hY2ZlODI2OTlkMmEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JFWKf7GZq1f8raP3Jm6rszpwPCh0JnaeZcHyC_AwcsNS6sJ9_qSY9wrbyHmvV9KIGMIPv23fymADZXb0ng7maeAv9NR34KiJqnKbmPeeWwL0cPoGOGOUICL6H5x1iTw7XaMDN2WQRrBRFuUkudybEF8n6fEGsAvcsXViaHjYwJyIEYCnHKPzuTvM1RjyGFsERpFXKls4UB_KhMBEonr4JOskupmX1pADBuicTNx_4whnd6ZDfiF5SSBohFV1ikwFOXK-qZ7znQfE-RJ-jV1CXBgEK8O66TMbMw9MbasS25xKoO0mH1_Ohf9niSXsY02o2qjGFZA9sWRk7K7pNgsxUw" + authPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI2NDcsImlhdCI6MTcxNTA5MjM0NywiYXV0aF90aW1lIjoxNzE1MDkyMzQ3LCJqdGkiOiI3NzkwZmVhNC1hNzcyLTRhZTMtOTcyMi0yMTU2MmQyZGM5YmYiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImFmNmViOTRiLWU4ZDQtNDNlYi1hYzYwLTI3YmZiYjNiOTQxZSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiYWY2ZWI5NGItZThkNC00M2ViLWFjNjAtMjdiZmJiM2I5NDFlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.BfCX_fq2Q6cv5qb6TWzyCNiJf1vFw_iA4UTKr21ahUiNItNSW5ozET2jSLwKNAuMdBNrooU--OV1NniDcviIAMReaAEgjmAyBz6OSwAh3SmxzIU9Zy7f4V032FLDcVVoJ7CefItfBNu7WnWFGS7CYahNX_M2a6LXKhk7WRO4gQ2Ig11gtODlAP8jwLLAMU4_H9mVHD3LXd-IeOsnA8ZuBCq1DeFcn5T9tNZEGe0_21lp8spxoub0MRl-vYbgxEIoaeqxoSipb2hOjF7h0h1uaNhZT4m5ynHdd5yfspD8XjjjwlbXQn9Z8vrZUQQS6HLAi2pJIFNEoYxQk9lHal6VUA" + authPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTI3NDAsImlhdCI6MTcxNTA5MjQ0MCwiYXV0aF90aW1lIjoxNzE1MDkyNDQwLCJqdGkiOiIzZjk2ZDhjNC0yMjRkLTQyNjAtYmVkMy1lOGY2N2IwYTJjM2EiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiZDI1ZjhhZTMtYzE0Yy00ZWFmLTkzOWMtZjhlNGIyYmE1NDY3IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJkMjVmOGFlMy1jMTRjLTRlYWYtOTM5Yy1mOGU0YjJiYTU0NjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.JphgIUbUeEEd25-Ji0o6_pcWvLzcQasCfr1z8WRt3xb1QrkN_d0_rmIpOJ9drhp8LjJPQRhFVxEU2TnAlYJ225IjPYolCrnEtKWsBbPJH9dP0cIJlilYplN4RZbmI9VbF578zAgVAs40n8aalNyxqYbPq_JViHDl_ufl4VEQ4Entzlp980I8whx3kfTygu0Yfl4eHLghPGt4LNPUmfeOIy8NKHbhmjHwKufrTmd0NV07cAOMUWl1NAF_4QWqmSqAY0SIcamwE7YlpuImzhj5PQH9tlyJMLr5m-k8CgKRfhpQ0H9cfVGUzWGG2A-lcNvxNmsk1kobmfHczjw13ajLKg" + implicitPrivClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUwOTM4MzgsImlhdCI6MTcxNTA5MjkzOCwiYXV0aF90aW1lIjoxNzE1MDkyOTM4LCJqdGkiOiI0ZWIzY2I1OS05ZDRhLTQwNjctYmI0YS1iMjNjNDVhMDIyYTIiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJzZXNzaW9uX3N0YXRlIjoiYmE1OWFmOTgtNmE3YS00YjRhLTliOTItODU1M2ZkM2EwMTNjIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLW9yZy1hZG1pbiIsImRlZmF1bHQtcm9sZXMtb3BlbnRkZiIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJ0ZGYtZW50aXR5LXJlc29sdXRpb24iOnsicm9sZXMiOlsiZW50aXR5LXJlc29sdXRpb24tdGVzdC1yb2xlIl19LCJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJxdWVyeS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIiwicXVlcnktdXNlcnMiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJiYTU5YWY5OC02YTdhLTRiNGEtOWI5Mi04NTUzZmQzYTAxM2MiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJzYW1wbGUgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InNhbXBsZS11c2VyIiwiZ2l2ZW5fbmFtZSI6InNhbXBsZSIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic2FtcGxldXNlckBzYW1wbGUuY29tIn0.KQasyQ-f9KBRWRDXg4NikiHlragVil1nlYTQ8czPKku_uncpHZb7PMJhyPrwy72mwC10EJMpBIWGDVRfRjBRHxdzIbjozcGg3vusX748NMiDSlF4KoB5Fz-qExszcszEP5Qm_fvMRFcW7m9RPW9St1aaHcjAOW5Vee9ACJI56YffgqrTn1xp7ha2Z2X8d_NJfJOFdP3cqgxjR7DV5RezkDLRPfxHwJLk3anavSuDScXIO1w1C6AlTUQFVQUEX0DKZIt-RbzKcd6HWBfyDvHUSlfodEI_diWQIL1hEfrBXV6ThuhTqhrghHyIbb2e-zoC20arjMAK0Tr7hMAY4acxgQ" + implicitPubClientJwt = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0OXRmSjByRUo4c0YzUjJ3Yi05eENHVXhYUEQ4RTZldmNsRG1hZ05EM3lBIn0.eyJleHAiOjE3MTUxNTE0MTMsImlhdCI6MTcxNTE1MDUxMywiYXV0aF90aW1lIjoxNzE1MTUwNTEzLCJqdGkiOiJlYTRmOGZiYS01ZjljLTRiMzQtYmU1ZC1jNTk2ZGI4YzNlYzkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODgvYXV0aC9yZWFsbXMvb3BlbnRkZiIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0Ojg4ODgiLCJ0ZGYtZW50aXR5LXJlc29sdXRpb24iLCJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiIyZTZjMTU4MC1jZmQzLTQzYWItYjE3My1mNmMzYmY4ZmY0ZTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZGYtZW50aXR5LXJlc29sdXRpb24tcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6ImRlM2U2ZDc1LTI3ODItNDg4NS1iYzU4LTU0MmJmYzEzNWNkNSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib3BlbnRkZi1vcmctYWRtaW4iLCJkZWZhdWx0LXJvbGVzLW9wZW50ZGYiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsidGRmLWVudGl0eS1yZXNvbHV0aW9uIjp7InJvbGVzIjpbImVudGl0eS1yZXNvbHV0aW9uLXRlc3Qtcm9sZSJdfSwicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiZGUzZTZkNzUtMjc4Mi00ODg1LWJjNTgtNTQyYmZjMTM1Y2Q1IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoic2FtcGxlIHVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzYW1wbGUtdXNlciIsImdpdmVuX25hbWUiOiJzYW1wbGUiLCJmYW1pbHlfbmFtZSI6InVzZXIiLCJlbWFpbCI6InNhbXBsZXVzZXJAc2FtcGxlLmNvbSJ9.jH60V3ZkuiN6cuEmbRTspnxyOvQs_wNkgoBw9IEZ8E8yGzXDayouduxEd_O-DG6vjT4KPDxGC2lA0V4i-ke7KChkZhRYLkaSuqt2hTlKoLXotepJPq8GBlXhWjCmFMqaXEB8lMAlAEoCT7CWmg03eTBGzwynj0S4rjMuOj6TLf3HIIN0DP7bgtG9uIc0Ah_mTVJ4L6Y5yjv6LC9bMZ7YNpUIkFn-CZTudquxHkLYgxHgaRAfELBvmS5xn0pTrpIfZSdYQK7hGhjhm9fUg4J06Pg6QW-xZe1U7awyNl7pOeeGQ2lVTo1CWrAlOz9lAmzKzAwQakEOMXFxAjJeHsXTWg" + tokenExchangeJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6ImE1NThkYzg0NzYzNDVjY2QyZWFhNjEzNjg4YmI2YTNkIn0.eyJleHAiOjE3MTU3OTA5MTAsImlhdCI6MTcxNTc5MDYxMCwianRpIjoiNjEyOTI2NzQtMDhmOS00ZmQ1LTk3Y2MtZDg3M2RhODRkZjllIiwiaXNzIjoiaHR0cHM6Ly9sb2NhbC1kc3AudmlydHJ1LmNvbTo4NDQzL2F1dGgvcmVhbG1zL29wZW50ZGYiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwiYWNjb3VudCIsIm9wZW50ZGYtc2RrIl0sInN1YiI6ImU2ZWI0YWU1LThjMDUtNDI3NC04ZmExLTFmMGY1ZmJjY2JkZiIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZW50ZGYiLCJzZXNzaW9uX3N0YXRlIjoiZTQ0YzMxNWMtNjk5Yy00NGFkLTk2NDUtNmRkMmIyMjgzN2JlIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvcGVudGRmLXJlYWRvbmx5IiwiZGVmYXVsdC1yb2xlcy1vcGVudGRmIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiJlNDRjMzE1Yy02OTljLTQ0YWQtOTY0NS02ZGQyYjIyODM3YmUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC1vcGVudGRmLXNkayJ9.dmAulsUNfdPXVyWmVPsbGqaztshyHTD-m2hh1l2hmhwuNISJZjON0e1kXNxYXRLABr_PJzIpGYQCXz98yxOyiw" +) func testKeycloakConfig(server *httptest.Server) keycloak.KeycloakConfig { return keycloak.KeycloakConfig{ @@ -108,8 +114,10 @@ func testServerResp(t *testing.T, w http.ResponseWriter, r *http.Request, k stri t.Errorf("UnExpected Request, got: %s", r.URL.Path) } } + func testServer(t *testing.T, userSearchQueryAndResp map[string]string, groupSearchQueryAndResp map[string]string, - groupByIDAndResponse map[string]string, groupMemberQueryAndResponse map[string]string, clientsSearchQueryAndResp map[string]string) *httptest.Server { + groupByIDAndResponse map[string]string, groupMemberQueryAndResponse map[string]string, clientsSearchQueryAndResp map[string]string, +) *httptest.Server { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch { case r.URL.Path == "/realms/tdf/protocol/openid-connect/token": @@ -141,22 +149,22 @@ func Test_KCEntityResolutionByClientId(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_ClientId{ClientId: "opentdf"}}) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody csqr := map[string]string{ "clientId=opentdf": byEmailBobResp, } server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) _ = json.NewEncoder(os.Stdout).Encode(&resp) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) } @@ -172,24 +180,24 @@ func Test_KCEntityResolutionByEmail(t *testing.T) { validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "bob@sample.org"}}) validBody = append(validBody, &authorization.Entity{Id: "1235", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "alice@sample.org"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 2) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "bobid", propMap["id"]) assert.Equal(t, "1235", entityRepresentations[1].GetOriginalId()) @@ -210,24 +218,24 @@ func Test_KCEntityResolutionByUsername(t *testing.T) { validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_UserName{UserName: "bob.smith"}}) validBody = append(validBody, &authorization.Entity{Id: "1235", EntityType: &authorization.Entity_UserName{UserName: "alice.smith"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 2) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "bobid", propMap["id"]) assert.Equal(t, "1235", entityRepresentations[1].GetOriginalId()) @@ -252,24 +260,24 @@ func Test_KCEntityResolutionByGroupEmail(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "123456", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "group1@sample.org"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) assert.Equal(t, "123456", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 2) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "bobid", propMap["id"]) propMap = entityRepresentations[0].GetAdditionalProps()[1].AsMap() assert.Equal(t, "aliceid", propMap["id"]) @@ -290,19 +298,19 @@ func Test_KCEntityResolutionNotFoundError(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "random@sample.org"}}) - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.Error(t, reserr) assert.Equal(t, &entityresolution.ResolveEntitiesResponse{}, &resp) - var entityNotFound = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrTextGetRetrievalFailed, Entity: "random@sample.org"} - var expectedError = status.Error(codes.Code(entityNotFound.GetCode()), entityNotFound.GetMessage()) + entityNotFound := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrGetRetrievalFailed.Error(), Entity: "random@sample.org"} + expectedError := connect.NewError(connect.Code(entityNotFound.GetCode()), keycloak.ErrGetRetrievalFailed) assert.Equal(t, expectedError, reserr) } @@ -313,13 +321,13 @@ func Test_JwtClientAndUsernameClientCredentials(t *testing.T) { server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: clientCredentialsJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -335,13 +343,13 @@ func Test_JwtClientAndUsernamePasswordPub(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: passwordPubClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -357,13 +365,13 @@ func Test_JwtClientAndUsernamePasswordPriv(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: passwordPrivClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -379,13 +387,13 @@ func Test_JwtClientAndUsernameAuthPub(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: authPubClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -401,13 +409,13 @@ func Test_JwtClientAndUsernameAuthPriv(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: authPrivClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -423,13 +431,13 @@ func Test_JwtClientAndUsernameImplicitPub(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: implicitPubClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -445,13 +453,13 @@ func Test_JwtClientAndUsernameImplicitPriv(t *testing.T) { server := testServer(t, nil, nil, nil, nil, nil) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: implicitPrivClientJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -470,13 +478,13 @@ func Test_JwtClientAndClientTokenExchange(t *testing.T) { server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: tokenExchangeJwt}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -495,13 +503,13 @@ func Test_JwtMultiple(t *testing.T) { server := testServer(t, nil, nil, nil, nil, csqr) defer server.Close() - var kcconfig = testKeycloakConfig(server) + kcconfig := testKeycloakConfig(server) - var ctxb = context.Background() + ctxb := context.Background() validBody := []*authorization.Token{{Jwt: tokenExchangeJwt, Id: "tok1"}, {Jwt: authPrivClientJwt, Id: "tok2"}} - var resp, reserr = keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) @@ -534,24 +542,24 @@ func Test_KCEntityResolutionNotFoundInferEmail(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "random@sample.org"}}) - var kcconfig = testKeycloakConfigInferID(server) + kcconfig := testKeycloakConfigInferID(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "random@sample.org", propMap["emailAddress"]) assert.Equal(t, "1234", propMap["id"]) } @@ -566,24 +574,24 @@ func Test_KCEntityResolutionNotFoundInferClientId(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_ClientId{ClientId: "random"}}) - var kcconfig = testKeycloakConfigInferID(server) + kcconfig := testKeycloakConfigInferID(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.NoError(t, reserr) - var entityRepresentations = resp.GetEntityRepresentations() + entityRepresentations := resp.GetEntityRepresentations() assert.NotNil(t, entityRepresentations) assert.Len(t, entityRepresentations, 1) assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) - var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + propMap := entityRepresentations[0].GetAdditionalProps()[0].AsMap() assert.Equal(t, "random", propMap["clientId"]) assert.Equal(t, "1234", propMap["id"]) } @@ -597,18 +605,18 @@ func Test_KCEntityResolutionNotFoundNotInferUsername(t *testing.T) { var validBody []*authorization.Entity validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_UserName{UserName: "randomuser"}}) - var kcconfig = testKeycloakConfigInferID(server) + kcconfig := testKeycloakConfigInferID(server) - var ctxb = context.Background() + ctxb := context.Background() - var req = entityresolution.ResolveEntitiesRequest{} + req := entityresolution.ResolveEntitiesRequest{} req.Entities = validBody - var resp, reserr = keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) + resp, reserr := keycloak.EntityResolution(ctxb, &req, kcconfig, logger.CreateTestLogger()) require.Error(t, reserr) assert.Equal(t, &entityresolution.ResolveEntitiesResponse{}, &resp) - var entityNotFound = entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrTextGetRetrievalFailed, Entity: "randomuser"} - var expectedError = status.Error(codes.Code(entityNotFound.GetCode()), entityNotFound.GetMessage()) + entityNotFound := entityresolution.EntityNotFoundError{Code: int32(codes.NotFound), Message: keycloak.ErrGetRetrievalFailed.Error(), Entity: "randomuser"} + expectedError := connect.NewError(connect.Code(entityNotFound.GetCode()), keycloak.ErrGetRetrievalFailed) assert.Equal(t, expectedError, reserr) } diff --git a/service/go.mod b/service/go.mod index 3056b9d5f4..4d865f9551 100644 --- a/service/go.mod +++ b/service/go.mod @@ -4,6 +4,8 @@ go 1.22 require ( connectrpc.com/connect v1.17.0 + connectrpc.com/grpcreflect v1.2.0 + connectrpc.com/validate v0.1.0 github.com/Masterminds/squirrel v1.5.4 github.com/Nerzal/gocloak/v13 v13.9.0 github.com/bmatcuk/doublestar v1.3.4 @@ -13,7 +15,6 @@ require ( github.com/go-chi/cors v1.2.1 github.com/go-playground/validator/v10 v10.22.0 github.com/google/uuid v1.6.0 - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa github.com/jackc/pgx/v5 v5.5.5 @@ -60,6 +61,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/gowebpki/jcs v1.0.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/userns v0.1.0 // indirect @@ -147,6 +149,7 @@ require ( ) require ( + connectrpc.com/grpchealth v1.3.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect diff --git a/service/go.sum b/service/go.sum index e64f2e4af6..582e2af098 100644 --- a/service/go.sum +++ b/service/go.sum @@ -2,6 +2,12 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-2024050820065 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.1-20240508200655-46a4cf4ba109.1/go.mod h1:XF+P8+RmfdufmIYpGUC+6bF7S+IlmHDEnCrO3OXaUAQ= connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= +connectrpc.com/grpchealth v1.3.0 h1:FA3OIwAvuMokQIXQrY5LbIy8IenftksTP/lG4PbYN+E= +connectrpc.com/grpchealth v1.3.0/go.mod h1:3vpqmX25/ir0gVgW6RdnCPPZRcR6HvqtXX5RNPmDXHM= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +connectrpc.com/validate v0.1.0 h1:r55jirxMK7HO/xZwVHj3w2XkVFarsUM77ZDy367NtH4= +connectrpc.com/validate v0.1.0/go.mod h1:GU47c9/x/gd+u9wRSPkrQOP46gx2rMN+Wo37EHgI3Ow= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= diff --git a/service/health/health.go b/service/health/health.go index 053da5dffc..01489f3a74 100644 --- a/service/health/health.go +++ b/service/health/health.go @@ -4,7 +4,7 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/grpchealth" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" @@ -15,64 +15,62 @@ import ( var serviceHealthChecks = make(map[string]func(context.Context) error) type HealthService struct { //nolint:revive // HealthService is a valid name for this struct - healthpb.UnimplementedHealthServer logger *logger.Logger } -func NewRegistration() *serviceregistry.Service[HealthService] { - return &serviceregistry.Service[HealthService]{ - ServiceOptions: serviceregistry.ServiceOptions[HealthService]{ - Namespace: "health", - ServiceDesc: &healthpb.Health_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*HealthService, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[grpchealth.Checker] { + return &serviceregistry.Service[grpchealth.Checker]{ + ServiceOptions: serviceregistry.ServiceOptions[grpchealth.Checker]{ + Namespace: "health", + ServiceDesc: &healthpb.Health_ServiceDesc, + ConnectRPCFunc: grpchealth.NewHandler, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (grpchealth.Checker, serviceregistry.HandlerServer) { err := srp.WellKnownConfig("health", map[string]any{ "endpoint": "/healthz", }) if err != nil { srp.Logger.Error("failed to set well-known config", slog.String("error", err.Error())) } - return &HealthService{logger: srp.Logger}, func(_ context.Context, _ *runtime.ServeMux) error { - return nil - } + return HealthService{logger: srp.Logger}, nil }, }, } } -func (s HealthService) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - if req.GetService() == "" { - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_SERVING, +func (s HealthService) Check(ctx context.Context, req *grpchealth.CheckRequest) (*grpchealth.CheckResponse, error) { + if req.Service == "" { + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusServing, }, nil } - switch req.GetService() { + switch req.Service { case "all": for service, check := range serviceHealthChecks { if err := check(ctx); err != nil { s.logger.ErrorContext(ctx, "service is not ready", slog.String("service", service), slog.String("error", err.Error())) - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_NOT_SERVING, + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusNotServing, }, nil } } default: - if check, ok := serviceHealthChecks[req.GetService()]; ok { + if check, ok := serviceHealthChecks[req.Service]; ok { if err := check(ctx); err != nil { - s.logger.ErrorContext(ctx, "service is not ready", slog.String("service", req.GetService()), slog.String("error", err.Error())) - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_NOT_SERVING, + s.logger.ErrorContext(ctx, "service is not ready", slog.String("service", req.Service), slog.String("error", err.Error())) + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusNotServing, }, nil } } else { - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_SERVICE_UNKNOWN, + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusUnknown, }, nil } } - return &healthpb.HealthCheckResponse{ - Status: healthpb.HealthCheckResponse_SERVING, + return &grpchealth.CheckResponse{ + Status: grpchealth.StatusServing, }, nil } diff --git a/service/health/health_test.go b/service/health/health_test.go index db39936c82..f7b45b8357 100644 --- a/service/health/health_test.go +++ b/service/health/health_test.go @@ -2,10 +2,12 @@ package health import ( "context" + "testing" + "connectrpc.com/grpchealth" + "github.com/opentdf/platform/service/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" - "google.golang.org/grpc/health/grpc_health_v1" ) type HealthCheckSuite struct { @@ -20,6 +22,10 @@ func (s *HealthCheckSuite) TearDownTest() { serviceHealthChecks = make(map[string]func(context.Context) error) } +func TestHealthCheckSuite(t *testing.T) { + suite.Run(t, new(HealthCheckSuite)) +} + func (s *HealthCheckSuite) TestRegisterReadinessCheck() { // TestRegisterReadinessCheck tests the registration of a health check. @@ -67,11 +73,11 @@ func (s *HealthCheckSuite) TestCheck() { s.Require().NoError(err) // Check the health check. - result, err := hs.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{ + result, err := hs.Check(context.Background(), &grpchealth.CheckRequest{ Service: "all", }) s.Require().NoError(err) - s.Equal("SERVING", result.GetStatus().String()) + s.Equal(grpchealth.StatusServing, result.Status) } func (s *HealthCheckSuite) TestCheckServiceUnknown() { @@ -79,28 +85,37 @@ func (s *HealthCheckSuite) TestCheckServiceUnknown() { hs := &HealthService{} // Check the health check. - result, err := hs.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{ + result, err := hs.Check(context.Background(), &grpchealth.CheckRequest{ Service: "unknown", }) s.Require().NoError(err) - s.Equal("SERVICE_UNKNOWN", result.GetStatus().String()) + s.Equal(grpchealth.StatusUnknown, result.Status) } func (s *HealthCheckSuite) TestCheckNotServing() { // TestCheckNotServing tests the health check when a service is not serving. - hs := &HealthService{} + lgr, err := logger.NewLogger(logger.Config{ + Output: "stdout", + Level: "info", + Type: "json", + }) + s.Require().NoError(err) + + hs := &HealthService{ + logger: lgr, + } // Register the health check. - err := RegisterReadinessCheck("failing", func(context.Context) error { + err = RegisterReadinessCheck("failing", func(context.Context) error { return assert.AnError }) s.Require().NoError(err) // Check the health check. - result, err := hs.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{ + result, err := hs.Check(context.Background(), &grpchealth.CheckRequest{ Service: "failing", }) s.Require().NoError(err) - s.Equal("NOT_SERVING", result.GetStatus().String()) + s.Equal(grpchealth.StatusNotServing, result.Status) } diff --git a/service/internal/auth/authn.go b/service/internal/auth/authn.go index b2eb4cc769..556ecdaa85 100644 --- a/service/internal/auth/authn.go +++ b/service/internal/auth/authn.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "connectrpc.com/connect" "github.com/bmatcuk/doublestar" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" @@ -22,9 +23,7 @@ import ( sdkAudit "github.com/opentdf/platform/sdk/audit" "github.com/opentdf/platform/service/logger" - "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -266,57 +265,57 @@ func (a Authentication) MuxHandler(handler http.Handler) http.Handler { } // UnaryServerInterceptor is a grpc interceptor that verifies the token in the metadata -func (a Authentication) UnaryServerInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { - // Allow health checks and other public routes to pass through - if slices.ContainsFunc(a.publicRoutes, a.isPublicRoute(info.FullMethod)) { //nolint:contextcheck // There is no way to pass a context here - return handler(ctx, req) - } - - // Get the metadata from the context - // The keys within metadata.MD are normalized to lowercase. - // See: https://godoc.org/google.golang.org/grpc/metadata#New - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, status.Error(codes.Unauthenticated, "missing metadata") - } +func (a Authentication) ConnectUnaryServerInterceptor() connect.UnaryInterceptorFunc { + interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { + return connect.UnaryFunc(func( + ctx context.Context, + req connect.AnyRequest, + ) (connect.AnyResponse, error) { + // Interceptor Logic + // Allow health checks and other public routes to pass through + if slices.ContainsFunc(a.publicRoutes, a.isPublicRoute(req.Spec().Procedure)) { //nolint:contextcheck // There is no way to pass a context here + return next(ctx, req) + } - // Verify the token - header := md["authorization"] - if len(header) < 1 { - return nil, status.Error(codes.Unauthenticated, "missing authorization header") - } + header := req.Header()["Authorization"] + if len(header) < 1 { + return nil, status.Error(codes.Unauthenticated, "missing authorization header") + } - // parse the rpc method - p := strings.Split(info.FullMethod, "/") - resource := p[1] + "/" + p[2] - action := getAction(p[2]) + // parse the rpc method + p := strings.Split(req.Spec().Procedure, "/") + resource := p[1] + "/" + p[2] + action := getAction(p[2]) + + token, newCtx, err := a.checkToken( + ctx, + header, + receiverInfo{ + u: req.Spec().Procedure, + m: http.MethodPost, + }, + req.Header()["Dpop"], + ) + if err != nil { + return nil, status.Errorf(codes.Unauthenticated, "unauthenticated") + } - token, newCtx, err := a.checkToken( - ctx, - header, - receiverInfo{ - u: info.FullMethod, - m: http.MethodPost, - }, - md["dpop"], - ) - if err != nil { - return nil, status.Errorf(codes.Unauthenticated, "unauthenticated") - } + // Check if the token is allowed to access the resource + if allowed, err := a.enforcer.Enforce(token, resource, action); err != nil { + if err.Error() == "permission denied" { + a.logger.Warn("permission denied", slog.String("azp", token.Subject()), slog.String("error", err.Error())) + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } + return nil, err + } else if !allowed { + a.logger.Warn("permission denied", slog.String("azp", token.Subject())) + return nil, status.Errorf(codes.PermissionDenied, "permission denied") + } - // Check if the token is allowed to access the resource - if allowed, err := a.enforcer.Enforce(token, resource, action); err != nil { - if err.Error() == "permission denied" { - a.logger.Warn("permission denied", slog.String("azp", token.Subject()), slog.String("error", err.Error())) - return nil, status.Errorf(codes.PermissionDenied, "permission denied") - } - return nil, err - } else if !allowed { - a.logger.Warn("permission denied", slog.String("azp", token.Subject())) - return nil, status.Errorf(codes.PermissionDenied, "permission denied") + return next(newCtx, req) + }) } - - return handler(newCtx, req) + return connect.UnaryInterceptorFunc(interceptor) } // getAction returns the action based on the rpc name diff --git a/service/internal/auth/authn_test.go b/service/internal/auth/authn_test.go index 875c818a07..a7d5ed86ae 100644 --- a/service/internal/auth/authn_test.go +++ b/service/internal/auth/authn_test.go @@ -20,12 +20,15 @@ import ( "testing" "time" + "connectrpc.com/connect" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/lestrrat-go/jwx/v2/jws" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/protocol/go/kas" + "github.com/opentdf/platform/protocol/go/kas/kasconnect" sdkauth "github.com/opentdf/platform/sdk/auth" + "github.com/opentdf/platform/service/internal/server/memhttp" "github.com/opentdf/platform/service/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -33,9 +36,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "google.golang.org/grpc/test/bufconn" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -57,24 +58,19 @@ type FakeAccessServiceServer struct { kas.UnimplementedAccessServiceServer } -func (f *FakeAccessServiceServer) Info(context.Context, *kas.InfoRequest) (*kas.InfoResponse, error) { - return &kas.InfoResponse{}, nil +func (f *FakeAccessServiceServer) PublicKey(_ context.Context, _ *connect.Request[kas.PublicKeyRequest]) (*connect.Response[kas.PublicKeyResponse], error) { + return &connect.Response[kas.PublicKeyResponse]{Msg: &kas.PublicKeyResponse{}}, status.Error(codes.Unauthenticated, "no public key for you") } -func (f *FakeAccessServiceServer) PublicKey(context.Context, *kas.PublicKeyRequest) (*kas.PublicKeyResponse, error) { - return &kas.PublicKeyResponse{}, status.Error(codes.Unauthenticated, "no public key for you") +func (f *FakeAccessServiceServer) LegacyPublicKey(_ context.Context, _ *connect.Request[kas.LegacyPublicKeyRequest]) (*connect.Response[wrapperspb.StringValue], error) { + return &connect.Response[wrapperspb.StringValue]{Msg: &wrapperspb.StringValue{}}, nil } -func (f *FakeAccessServiceServer) LegacyPublicKey(context.Context, *kas.LegacyPublicKeyRequest) (*wrapperspb.StringValue, error) { - return &wrapperspb.StringValue{}, nil -} +func (f *FakeAccessServiceServer) Rewrap(ctx context.Context, req *connect.Request[kas.RewrapRequest]) (*connect.Response[kas.RewrapResponse], error) { + f.accessToken = req.Header()["Authorization"] + f.dpopKey = GetJWKFromContext(ctx, logger.CreateTestLogger()) -func (f *FakeAccessServiceServer) Rewrap(ctx context.Context, _ *kas.RewrapRequest) (*kas.RewrapResponse, error) { - if md, ok := metadata.FromIncomingContext(ctx); ok { - f.accessToken = md.Get("authorization") - f.dpopKey = GetJWKFromContext(ctx, logger.CreateTestLogger()) - } - return &kas.RewrapResponse{}, nil + return &connect.Response[kas.RewrapResponse]{Msg: &kas.RewrapResponse{}}, nil } type FakeTokenSource struct { @@ -230,11 +226,22 @@ func (s *AuthSuite) Test_MuxHandler_When_Authorization_Header_Missing_Expect_Err } func (s *AuthSuite) Test_UnaryServerInterceptor_When_Authorization_Header_Missing_Expect_Error() { - md := metadata.New(map[string]string{}) - ctx := metadata.NewIncomingContext(context.Background(), md) - _, err := s.auth.UnaryServerInterceptor(ctx, "test", &grpc.UnaryServerInfo{ - FullMethod: "/test", - }, nil) + // Create the interceptor + interceptor := s.auth.ConnectUnaryServerInterceptor() + + // Create a dummy next handler + next := func(_ context.Context, _ connect.AnyRequest) (connect.AnyResponse, error) { + // Return a dummy response + return connect.NewResponse[string](nil), nil + } + + // Create a request + req := connect.NewRequest[string](nil) + + _, err := interceptor(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + return next(ctx, req) + })(context.Background(), req) + s.Require().Error(err) s.Require().ErrorIs(err, status.Error(codes.Unauthenticated, "missing authorization header")) } @@ -430,20 +437,16 @@ func (s *AuthSuite) TestDPoPEndToEnd_GRPC() { signedTok, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, s.key)) s.Require().NoError(err) - buffer := 1024 * 1024 - listener := bufconn.Listen(buffer) - - server := grpc.NewServer(grpc.UnaryInterceptor(s.auth.UnaryServerInterceptor)) - defer server.Stop() + interceptor := connect.WithInterceptors(s.auth.ConnectUnaryServerInterceptor()) fakeServer := &FakeAccessServiceServer{} - kas.RegisterAccessServiceServer(server, fakeServer) - go func() { - err := server.Serve(listener) - if err != nil { - panic(err) - } - }() + + mux := http.NewServeMux() + path, handler := kasconnect.NewAccessServiceHandler(fakeServer, interceptor) + mux.Handle(path, handler) + + server := memhttp.New(mux) + defer server.Close() addingInterceptor := sdkauth.NewTokenAddingInterceptor(&FakeTokenSource{ key: dpopKey, @@ -452,8 +455,8 @@ func (s *AuthSuite) TestDPoPEndToEnd_GRPC() { MinVersion: tls.VersionTLS12, }) - conn, _ := grpc.NewClient("passthrough://bufconn", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { - return listener.Dial() + conn, _ := grpc.NewClient("passthrough://bufconn", grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { + return server.Listener.DialContext(ctx, "tcp", "http://localhost:8080") }), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUnaryInterceptor(addingInterceptor.AddCredentials)) client := kas.NewAccessServiceClient(conn) diff --git a/service/internal/server/realip/realip.go b/service/internal/server/realip/realip.go index 80bd680587..5ecdbc7bed 100644 --- a/service/internal/server/realip/realip.go +++ b/service/internal/server/realip/realip.go @@ -16,7 +16,7 @@ const ( TrueClientIP = "True-Client-Ip" ) -type clientIP struct{} +type ClientIP struct{} func ConnectRealIPUnaryInterceptor() connect.UnaryInterceptorFunc { interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { @@ -26,7 +26,7 @@ func ConnectRealIPUnaryInterceptor() connect.UnaryInterceptorFunc { ) (connect.AnyResponse, error) { ip := getIP(ctx, req.Peer(), req.Header()) - ctx = context.WithValue(ctx, clientIP{}, ip) + ctx = context.WithValue(ctx, ClientIP{}, ip) return next(ctx, req) }) @@ -54,7 +54,7 @@ func getIP(_ context.Context, peer connect.Peer, headers http.Header) net.IP { } func FromContext(ctx context.Context) net.IP { - ip, ok := ctx.Value(clientIP{}).(net.IP) + ip, ok := ctx.Value(ClientIP{}).(net.IP) if !ok { return net.IP{} } diff --git a/service/internal/server/server.go b/service/internal/server/server.go index f923730e76..b1aa79032a 100644 --- a/service/internal/server/server.go +++ b/service/internal/server/server.go @@ -9,14 +9,14 @@ import ( "net" "net/http" "net/http/pprof" - "net/netip" + "regexp" "strings" "time" - "github.com/bufbuild/protovalidate-go" + "connectrpc.com/connect" + "connectrpc.com/grpcreflect" + "connectrpc.com/validate" "github.com/go-chi/cors" - protovalidate_middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/protovalidate" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" sdkAudit "github.com/opentdf/platform/sdk/audit" "github.com/opentdf/platform/service/internal/auth" @@ -27,10 +27,7 @@ import ( "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" - healthpb "google.golang.org/grpc/health/grpc_health_v1" - "google.golang.org/grpc/reflection" ) const ( @@ -104,13 +101,19 @@ type CORSConfig struct { MaxAge int `mapstructure:"maxage" json:"maxage" default:"3600"` } +type ConnectRPC struct { + Mux *http.ServeMux + Interceptors []connect.HandlerOption + ServiceReflection []string +} + type OpenTDFServer struct { - AuthN *auth.Authentication - Mux *runtime.ServeMux - HTTPServer *http.Server - GRPCServer *grpc.Server - GRPCInProcess *inProcessServer - CryptoProvider security.CryptoProvider + AuthN *auth.Authentication + GRPCGatewayMux *runtime.ServeMux + HTTPServer *http.Server + ConnectRPCInProcess *inProcessServer + ConnectRPC *ConnectRPC + CryptoProvider security.CryptoProvider logger *logger.Logger } @@ -122,11 +125,10 @@ https://github.com/heroku/x/blob/master/grpc/grpcserver/inprocess.go https://github.com/valyala/fasthttp/blob/master/fasthttputil/inmemory_listener.go */ type inProcessServer struct { - ln *memhttp.Server - srv *grpc.Server - + srv *memhttp.Server maxCallRecvMsgSize int maxCallSendMsgSize int + *ConnectRPC } func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, error) { @@ -152,37 +154,37 @@ func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, err logger.Warn("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP set `enforceDPoP = false`") } - // Create grpc server and in process grpc server - grpcServer, err := newGrpcServer(config, authN, logger) + connectRPCIpc, err := newConnectRPCIPC() if err != nil { - return nil, fmt.Errorf("failed to create grpc server: %w", err) + return nil, fmt.Errorf("failed to create connect rpc ipc server: %w", err) } - grpcInProcessServer := newGrpcInProcessServer() - - grpcIPCServer := &inProcessServer{ - ln: memhttp.New(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { grpcInProcessServer.ServeHTTP(w, r) })), - srv: grpcInProcessServer, - maxCallRecvMsgSize: config.GRPC.MaxCallRecvMsgSizeBytes, - maxCallSendMsgSize: config.GRPC.MaxCallSendMsgSizeBytes, + connectRPC, err := newConnectRPC(config, authN, logger) + if err != nil { + return nil, fmt.Errorf("failed to create connect rpc server: %w", err) } + // GRPC Gateway Mux + grpcGatewayMux := runtime.NewServeMux() + // Create http server - mux := runtime.NewServeMux( - runtime.WithHealthzEndpoint(healthpb.NewHealthClient(grpcIPCServer.Conn())), - ) - httpServer, err := newHTTPServer(config, mux, authN, grpcServer, logger) + httpServer, err := newHTTPServer(config, connectRPC.Mux, grpcGatewayMux, authN, logger) if err != nil { return nil, fmt.Errorf("failed to create http server: %w", err) } o := OpenTDFServer{ - AuthN: authN, - Mux: mux, - HTTPServer: httpServer, - GRPCServer: grpcServer, - GRPCInProcess: grpcIPCServer, - logger: logger, + AuthN: authN, + GRPCGatewayMux: grpcGatewayMux, + HTTPServer: httpServer, + ConnectRPC: connectRPC, + ConnectRPCInProcess: &inProcessServer{ + srv: memhttp.New(connectRPCIpc.Mux), + maxCallRecvMsgSize: config.GRPC.MaxCallRecvMsgSizeBytes, + maxCallSendMsgSize: config.GRPC.MaxCallSendMsgSizeBytes, + ConnectRPC: connectRPCIpc, + }, + logger: logger, } // Create crypto provider @@ -195,25 +197,52 @@ func NewOpenTDFServer(config Config, logger *logger.Logger) (*OpenTDFServer, err return &o, nil } +// Custom response writer to add deprecation header +type grpcGatewayResponseWriter struct { + w http.ResponseWriter + code int + wroteHeader bool +} + +func (rw *grpcGatewayResponseWriter) Header() http.Header { + return rw.w.Header() +} + +func (rw *grpcGatewayResponseWriter) WriteHeader(statusCode int) { + gRPCGatewayDeprecationDate := fmt.Sprintf("@%d", time.Date(2025, time.March, 25, 0, 0, 0, 0, time.UTC).Unix()) + if !rw.wroteHeader { + rw.w.Header().Set("Deprecation", gRPCGatewayDeprecationDate) + rw.wroteHeader = true + rw.w.WriteHeader(statusCode) + } + rw.code = statusCode +} + +func (rw *grpcGatewayResponseWriter) Write(data []byte) (int, error) { + // Ensure headers are written before any data + if !rw.wroteHeader { + rw.WriteHeader(http.StatusOK) + } + return rw.w.Write(data) +} + // newHTTPServer creates a new http server with the given handler and grpc server -func newHTTPServer(c Config, h http.Handler, a *auth.Authentication, g *grpc.Server, l *logger.Logger) (*http.Server, error) { +func newHTTPServer(c Config, connectRPC http.Handler, originalGrpcGateway http.Handler, a *auth.Authentication, l *logger.Logger) (*http.Server, error) { var ( err error tc *tls.Config writeTimeoutOverride = writeTimeout ) - // Add authN interceptor - // This is needed because we are leveraging RegisterXServiceHandlerServer instead of RegisterXServiceHandlerFromEndpoint - if c.Auth.Enabled { - h = a.MuxHandler(h) - } else { - l.Error("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP set `enforceDPoP = false`") - } + // Adds deprecation header to any grpcGateway responses. + var grpcGateway http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + grpcRW := &grpcGatewayResponseWriter{w: w, code: http.StatusOK} + originalGrpcGateway.ServeHTTP(grpcRW, r) + }) // CORS if c.CORS.Enabled { - h = cors.New(cors.Options{ + corsHandler := cors.New(cors.Options{ AllowOriginFunc: func(_ *http.Request, origin string) bool { for _, allowedOrigin := range c.CORS.AllowedOrigins { if allowedOrigin == "*" { @@ -230,37 +259,60 @@ func newHTTPServer(c Config, h http.Handler, a *auth.Authentication, g *grpc.Ser ExposedHeaders: c.CORS.ExposedHeaders, AllowCredentials: c.CORS.AllowCredentials, MaxAge: c.CORS.MaxAge, - }).Handler(h) + }) + + // Apply CORS to connectRPC and extra handlers + connectRPC = corsHandler.Handler(connectRPC) + grpcGateway = corsHandler.Handler(grpcGateway) + } + + // Add authN interceptor to extra handlers + if c.Auth.Enabled { + grpcGateway = a.MuxHandler(grpcGateway) + } else { + l.Error("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP set `enforceDPoP = false`") } // Enable pprof if c.EnablePprof { - h = pprofHandler(h) + grpcGateway = pprofHandler(grpcGateway) // Need to extend write timeout to collect pprof data. writeTimeoutOverride = 30 * time.Second //nolint:mnd // easier to read that we are overriding the default } - // Add grpc handler - h2 := httpGrpcHandlerFunc(h, g, l) - + var handler http.Handler if !c.TLS.Enabled { - h2 = h2c.NewHandler(h2, &http2.Server{}) + handler = h2c.NewHandler(routeConnectRPCRequests(connectRPC, grpcGateway), &http2.Server{}) } else { tc, err = loadTLSConfig(c.TLS) if err != nil { return nil, fmt.Errorf("failed to load tls config: %w", err) } + handler = routeConnectRPCRequests(connectRPC, grpcGateway) } return &http.Server{ Addr: fmt.Sprintf("%s:%d", c.Host, c.Port), WriteTimeout: writeTimeoutOverride, ReadTimeout: readTimeout, - Handler: h2, + Handler: handler, TLSConfig: tc, }, nil } +var rpcPathRegex = regexp.MustCompile(`^/[\w\.]+\.[\w\.]+/[\w]+$`) + +func routeConnectRPCRequests(connectRPC http.Handler, httpHandler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // contentType := r.Header.Get("Content-Type") + if (r.Method == http.MethodPost || r.Method == http.MethodGet) && rpcPathRegex.MatchString(r.URL.Path) { + connectRPC.ServeHTTP(w, r) + } else { + httpHandler.ServeHTTP(w, r) + } + }) +} + // ppprof handler func pprofHandler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -283,91 +335,58 @@ func pprofHandler(h http.Handler) http.Handler { }) } -// httpGrpcHandlerFunc returns a http.Handler that delegates to the grpc server if the request is a grpc request -func httpGrpcHandlerFunc(h http.Handler, g *grpc.Server, l *logger.Logger) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - l.TraceContext(r.Context(), "grpc handler func", slog.Int("proto_major", r.ProtoMajor), slog.String("content_type", r.Header.Get("Content-Type"))) - if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { - g.ServeHTTP(w, r) - } else { - h.ServeHTTP(w, r) - } - }) -} - -func newGrpcInProcessServer() *grpc.Server { - var interceptors []grpc.UnaryServerInterceptor - var serverOptions []grpc.ServerOption +func newConnectRPCIPC() (*ConnectRPC, error) { + interceptors := make([]connect.HandlerOption, 0) - // Add audit to in process server - interceptors = append(interceptors, audit.ContextServerInterceptor) + // Add protovalidate interceptor + vaidationInterceptor, err := validate.NewInterceptor() + if err != nil { + return nil, fmt.Errorf("failed to create validation interceptor: %w", err) + } - // FIXME: this should probably use existing IP address instead of local? - // Add RealIP interceptor to in process server - // trustedPeers := []netip.Prefix{} // TODO: add this as a config option? - // headers := []string{realip.XForwardedFor, realip.XRealIp} - // interceptors = append(interceptors, realip.UnaryServerInterceptor(trustedPeers, headers)) + interceptors = append(interceptors, connect.WithInterceptors(vaidationInterceptor, audit.ContextServerInterceptor())) - // Add interceptors to server options - serverOptions = append(serverOptions, grpc.ChainUnaryInterceptor(interceptors...)) - return grpc.NewServer(serverOptions...) + return &ConnectRPC{ + Interceptors: interceptors, + Mux: http.NewServeMux(), + }, nil } -// newGrpcServer creates a new grpc server with the given config and authN interceptor -func newGrpcServer(c Config, a *auth.Authentication, logger *logger.Logger) (*grpc.Server, error) { - var i []grpc.UnaryServerInterceptor - var o []grpc.ServerOption +func newConnectRPC(c Config, a *auth.Authentication, logger *logger.Logger) (*ConnectRPC, error) { + interceptors := make([]connect.HandlerOption, 0) - // Enable proto validation - validator, err := protovalidate.New() + // Add protovalidate interceptor + vaidationInterceptor, err := validate.NewInterceptor() if err != nil { - logger.Warn("failed to create proto validator", slog.String("error", err.Error())) + return nil, fmt.Errorf("failed to create validation interceptor: %w", err) } - // Add Audit Unary Server Interceptor - i = append(i, audit.ContextServerInterceptor) + interceptors = append(interceptors, connect.WithInterceptors(vaidationInterceptor, audit.ContextServerInterceptor())) if c.Auth.Enabled { - i = append(i, a.UnaryServerInterceptor) + interceptors = append(interceptors, connect.WithInterceptors(a.ConnectUnaryServerInterceptor())) } else { logger.Error("disabling authentication. this is deprecated and will be removed. if you are using an IdP without DPoP you can set `enforceDpop = false`") } - // Add tls creds if tls is not nil - if c.TLS.Enabled { - c, err := loadTLSConfig(c.TLS) - if err != nil { - return nil, fmt.Errorf("failed to load tls config: %w", err) - } - o = append(o, grpc.Creds(credentials.NewTLS(c))) - } - - // Add proto validation interceptor - i = append(i, protovalidate_middleware.UnaryServerInterceptor(validator)) - - o = append(o, grpc.ChainUnaryInterceptor( - i..., - )) - - // Chain relaip interceptor - trustedPeers := []netip.Prefix{} // TODO: add this as a config option? - headers := []string{realip.XForwardedFor, realip.XRealIp} - - o = append(o, grpc.ChainUnaryInterceptor( - realip.UnaryServerInterceptor(trustedPeers, headers), - )) + return &ConnectRPC{ + Interceptors: interceptors, + Mux: http.NewServeMux(), + }, nil +} - s := grpc.NewServer(o...) +func (s OpenTDFServer) Start() error { + // Add reflection api to connect-rpc + reflector := grpcreflect.NewStaticReflector( + s.ConnectRPC.ServiceReflection..., + ) - // Enable grpc reflection - if c.GRPC.ReflectionEnabled { - reflection.Register(s) - } + s.ConnectRPC.Mux.Handle(grpcreflect.NewHandlerV1(reflector)) + s.ConnectRPC.Mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector)) - return s, nil -} + s.ConnectRPCInProcess.Mux.Handle(grpcreflect.NewHandlerV1(reflector)) + s.ConnectRPCInProcess.Mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector)) -func (s OpenTDFServer) Start() error { // Start Http Server ln, err := s.openHTTPServerPort() if err != nil { @@ -375,8 +394,6 @@ func (s OpenTDFServer) Start() error { } go s.startHTTPServer(ln) - // Start In Process Grpc Server - go s.startInProcessGrpcServer() return nil } @@ -390,15 +407,14 @@ func (s OpenTDFServer) Stop() { } s.logger.Info("shutting down in process grpc server") - s.GRPCInProcess.srv.GracefulStop() + if err := s.ConnectRPCInProcess.srv.Shutdown(ctx); err != nil { + s.logger.Error("failed to shutdown in process connect-rpc server", slog.String("error", err.Error())) + return + } s.logger.Info("shutdown complete") } -func (s inProcessServer) GetGrpcServer() *grpc.Server { - return s.srv -} - func (s inProcessServer) Conn() *grpc.ClientConn { var clientInterceptors []grpc.UnaryClientInterceptor @@ -411,7 +427,7 @@ func (s inProcessServer) Conn() *grpc.ClientConn { grpc.MaxCallSendMsgSize(s.maxCallSendMsgSize), ), grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { - conn, err := s.ln.Listener.DialContext(ctx, "inprocess", "") + conn, err := s.srv.Listener.DialContext(ctx, "tcp", "http://localhost:8080") if err != nil { return nil, fmt.Errorf("failed to dial in process grpc server: %w", err) } @@ -425,12 +441,14 @@ func (s inProcessServer) Conn() *grpc.ClientConn { return conn } -func (s OpenTDFServer) startInProcessGrpcServer() { - s.logger.Info("starting in process grpc server") - if err := s.GRPCInProcess.srv.Serve(s.GRPCInProcess.ln.Listener); err != nil { - s.logger.Error("failed to serve in process grpc", slog.String("error", err.Error())) - panic(err) - } +func (s *inProcessServer) WithContextDialer() grpc.DialOption { + return grpc.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { + conn, err := s.srv.Listener.DialContext(ctx, "tcp", "http://localhost:8080") + if err != nil { + return nil, fmt.Errorf("failed to dial in process grpc server: %w", err) + } + return conn, nil + }) } func (s OpenTDFServer) openHTTPServerPort() (net.Listener, error) { diff --git a/service/kas/access/publicKey.go b/service/kas/access/publicKey.go index 19dde9b9dc..ca810c53cc 100644 --- a/service/kas/access/publicKey.go +++ b/service/kas/access/publicKey.go @@ -8,6 +8,7 @@ import ( "encoding/pem" "errors" + "connectrpc.com/connect" kaspb "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/service/internal/security" "google.golang.org/grpc/codes" @@ -23,7 +24,7 @@ const ( func (p Provider) lookupKid(ctx context.Context, algorithm string) (string, error) { if len(p.KASConfig.Keyring) == 0 { p.Logger.WarnContext(ctx, "no default keys found", "algorithm", algorithm) - return "", errors.Join(ErrConfig, status.Error(codes.NotFound, "no default keys configured")) + return "", connect.NewError(connect.CodeNotFound, errors.Join(ErrConfig, errors.New("no default keys configured"))) } for _, k := range p.KASConfig.Keyring { @@ -32,18 +33,18 @@ func (p Provider) lookupKid(ctx context.Context, algorithm string) (string, erro } } p.Logger.WarnContext(ctx, "no (non-legacy) key for requested algorithm", "algorithm", algorithm) - return "", errors.Join(ErrConfig, status.Error(codes.NotFound, "no default key for algorithm")) + return "", connect.NewError(connect.CodeNotFound, errors.Join(ErrConfig, errors.New("no default key for algorithm"))) } -func (p Provider) LegacyPublicKey(ctx context.Context, in *kaspb.LegacyPublicKeyRequest) (*wrapperspb.StringValue, error) { - algorithm := in.GetAlgorithm() +func (p Provider) LegacyPublicKey(ctx context.Context, req *connect.Request[kaspb.LegacyPublicKeyRequest]) (*connect.Response[wrapperspb.StringValue], error) { + algorithm := req.Msg.GetAlgorithm() if algorithm == "" { algorithm = security.AlgorithmRSA2048 } var pem string var err error if p.CryptoProvider == nil { - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, errors.Join(ErrConfig, errors.New("configuration error"))) } kid, err := p.lookupKid(ctx, algorithm) if err != nil { @@ -55,7 +56,7 @@ func (p Provider) LegacyPublicKey(ctx context.Context, in *kaspb.LegacyPublicKey pem, err = p.CryptoProvider.ECCertificate(kid) if err != nil { p.Logger.ErrorContext(ctx, "CryptoProvider.ECPublicKey failed", "err", err) - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, errors.Join(ErrConfig, errors.New("configuration error"))) } case security.AlgorithmRSA2048: fallthrough @@ -63,38 +64,38 @@ func (p Provider) LegacyPublicKey(ctx context.Context, in *kaspb.LegacyPublicKey pem, err = p.CryptoProvider.RSAPublicKey(kid) if err != nil { p.Logger.ErrorContext(ctx, "CryptoProvider.RSAPublicKey failed", "err", err) - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, errors.Join(ErrConfig, errors.New("configuration error"))) } default: - return nil, errors.Join(ErrConfig, status.Error(codes.NotFound, "invalid algorithm")) + return nil, connect.NewError(connect.CodeNotFound, errors.Join(ErrConfig, errors.New("invalid algorithm"))) } - return &wrapperspb.StringValue{Value: pem}, nil + return connect.NewResponse(&wrapperspb.StringValue{Value: pem}), nil } -func (p Provider) PublicKey(ctx context.Context, in *kaspb.PublicKeyRequest) (*kaspb.PublicKeyResponse, error) { - algorithm := in.GetAlgorithm() +func (p Provider) PublicKey(ctx context.Context, req *connect.Request[kaspb.PublicKeyRequest]) (*connect.Response[kaspb.PublicKeyResponse], error) { + algorithm := req.Msg.GetAlgorithm() if algorithm == "" { algorithm = security.AlgorithmRSA2048 } - fmt := in.GetFmt() + fmt := req.Msg.GetFmt() kid, err := p.lookupKid(ctx, algorithm) if err != nil { return nil, err } - r := func(value, kid string, err error) (*kaspb.PublicKeyResponse, error) { + r := func(value, kid string, err error) (*connect.Response[kaspb.PublicKeyResponse], error) { if errors.Is(err, security.ErrCertNotFound) { p.Logger.ErrorContext(ctx, "no key found for", "err", err, "kid", kid, "algorithm", algorithm, "fmt", fmt) - return nil, errors.Join(err, status.Error(codes.NotFound, "no such key")) + return nil, connect.NewError(connect.CodeNotFound, err) } else if err != nil { p.Logger.ErrorContext(ctx, "configuration error for key lookup", "err", err, "kid", kid, "algorithm", algorithm, "fmt", fmt) - return nil, errors.Join(ErrConfig, status.Error(codes.Internal, "configuration error")) + return nil, connect.NewError(connect.CodeInternal, err) } - if in.GetV() == "1" { - p.Logger.WarnContext(ctx, "hiding kid in public key response for legacy client", "kid", kid, "v", in.GetV()) - return &kaspb.PublicKeyResponse{PublicKey: value}, nil + if req.Msg.GetV() == "1" { + p.Logger.WarnContext(ctx, "hiding kid in public key response for legacy client", "kid", kid, "v", req.Msg.GetV()) + return connect.NewResponse(&kaspb.PublicKeyResponse{PublicKey: value}), nil } - return &kaspb.PublicKeyResponse{PublicKey: value, Kid: kid}, nil + return connect.NewResponse(&kaspb.PublicKeyResponse{PublicKey: value, Kid: kid}), nil } switch algorithm { diff --git a/service/kas/access/publicKey_test.go b/service/kas/access/publicKey_test.go index e469ddd5e7..a01e74a7c2 100644 --- a/service/kas/access/publicKey_test.go +++ b/service/kas/access/publicKey_test.go @@ -13,13 +13,12 @@ import ( "os" "testing" + "connectrpc.com/connect" kaspb "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/service/internal/security" "github.com/opentdf/platform/service/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) func TestExportRsaPublicKeyAsPemStrSuccess(t *testing.T) { @@ -101,7 +100,7 @@ func TestStandardCertificateHandlerEmpty(t *testing.T) { Logger: logger.CreateTestLogger(), } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{Fmt: "pkcs8"}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{Msg: &kaspb.PublicKeyRequest{Fmt: "pkcs8"}}) require.Error(t, err, "not found") assert.Nil(t, result) } @@ -147,10 +146,10 @@ func TestStandardPublicKeyHandlerV2(t *testing.T) { }, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{Msg: &kaspb.PublicKeyRequest{}}) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetPublicKey(), "BEGIN PUBLIC KEY") } func TestStandardPublicKeyHandlerV2Failure(t *testing.T) { @@ -166,7 +165,7 @@ func TestStandardPublicKeyHandlerV2Failure(t *testing.T) { Logger: logger.CreateTestLogger(), } - k, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{}) + k, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{Msg: &kaspb.PublicKeyRequest{}}) assert.Nil(t, k) require.Error(t, err) } @@ -192,14 +191,16 @@ func TestStandardPublicKeyHandlerV2NotFound(t *testing.T) { Logger: logger.CreateTestLogger(), } - k, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{ - Algorithm: "algorithm:unknown", + k, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "algorithm:unknown", + }, }) assert.Nil(t, k) require.Error(t, err) - status, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.NotFound, status.Code()) + + status := connect.CodeOf(err) + assert.Equal(t, connect.CodeNotFound, status) } func TestStandardPublicKeyHandlerV2WithJwk(t *testing.T) { @@ -230,14 +231,16 @@ func TestStandardPublicKeyHandlerV2WithJwk(t *testing.T) { }, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{ - Algorithm: "rsa:2048", - V: "2", - Fmt: "jwk", + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "rsa:2048", + V: "2", + Fmt: "jwk", + }, }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "\"kty\"") + assert.Contains(t, result.Msg.GetPublicKey(), "\"kty\"") } func TestStandardCertificateHandlerWithEc256(t *testing.T) { @@ -261,10 +264,14 @@ func TestStandardCertificateHandlerWithEc256(t *testing.T) { CryptoProvider: c, } - result, err := kas.LegacyPublicKey(context.Background(), &kaspb.LegacyPublicKeyRequest{Algorithm: "ec:secp256r1"}) + result, err := kas.LegacyPublicKey(context.Background(), &connect.Request[kaspb.LegacyPublicKeyRequest]{ + Msg: &kaspb.LegacyPublicKeyRequest{ + Algorithm: "ec:secp256r1", + }, + }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetValue(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetValue(), "BEGIN PUBLIC KEY") } func TestStandardPublicKeyHandlerWithEc256(t *testing.T) { @@ -288,10 +295,14 @@ func TestStandardPublicKeyHandlerWithEc256(t *testing.T) { CryptoProvider: c, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{Algorithm: "ec:secp256r1"}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "ec:secp256r1", + }, + }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetPublicKey(), "BEGIN PUBLIC KEY") } func TestStandardPublicKeyHandlerV2WithEc256(t *testing.T) { @@ -315,9 +326,13 @@ func TestStandardPublicKeyHandlerV2WithEc256(t *testing.T) { CryptoProvider: c, } - result, err := kas.PublicKey(context.Background(), &kaspb.PublicKeyRequest{Algorithm: "ec:secp256r1", - V: "2"}) + result, err := kas.PublicKey(context.Background(), &connect.Request[kaspb.PublicKeyRequest]{ + Msg: &kaspb.PublicKeyRequest{ + Algorithm: "ec:secp256r1", + V: "2", + }, + }) require.NoError(t, err) require.NotNil(t, result) - assert.Contains(t, result.GetPublicKey(), "BEGIN PUBLIC KEY") + assert.Contains(t, result.Msg.GetPublicKey(), "BEGIN PUBLIC KEY") } diff --git a/service/kas/access/rewrap.go b/service/kas/access/rewrap.go index bec70fb6ca..178a7ed108 100644 --- a/service/kas/access/rewrap.go +++ b/service/kas/access/rewrap.go @@ -16,9 +16,11 @@ import ( "errors" "fmt" "log/slog" + "net/http" "strings" "time" + "connectrpc.com/connect" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/lestrrat-go/jwx/v2/jwt" @@ -32,7 +34,6 @@ import ( "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -63,15 +64,15 @@ const ( ) func err400(s string) error { - return errors.Join(ErrUser, status.Error(codes.InvalidArgument, s)) + return connect.NewError(connect.CodeInvalidArgument, errors.Join(ErrUser, status.Error(codes.InvalidArgument, s))) } func err401(s string) error { - return errors.Join(ErrUser, status.Error(codes.Unauthenticated, s)) + return connect.NewError(connect.CodeUnauthenticated, errors.Join(ErrUser, status.Error(codes.Unauthenticated, s))) } func err403(s string) error { - return errors.Join(ErrUser, status.Error(codes.PermissionDenied, s)) + return connect.NewError(connect.CodePermissionDenied, errors.Join(ErrUser, status.Error(codes.PermissionDenied, s))) } func generateHMACDigest(ctx context.Context, msg, key []byte, logger logger.Logger) ([]byte, error) { @@ -119,14 +120,9 @@ func justRequestBody(ctx context.Context, token jwt.Token, logger logger.Logger) return rbString, nil } -func extractSRTBody(ctx context.Context, in *kaspb.RewrapRequest, logger logger.Logger) (*RequestBody, error) { +func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRequest, logger logger.Logger) (*RequestBody, error) { // First load legacy method for verifying SRT - md, exists := metadata.FromIncomingContext(ctx) - if !exists { - logger.WarnContext(ctx, "missing metadata for srt validation") - return nil, errors.New("missing metadata") - } - if vpk, ok := md["X-Virtrupubkey"]; ok && len(vpk) == 1 { + if vpk, ok := headers["X-Virtrupubkey"]; ok && len(vpk) == 1 { logger.InfoContext(ctx, "Legacy Client: Processing X-Virtrupubkey") } @@ -190,6 +186,7 @@ func extractSRTBody(ctx context.Context, in *kaspb.RewrapRequest, logger logger. return nil, err400("clientPublicKey unsupported type") } } + func extractPolicyBinding(policyBinding interface{}) (string, error) { switch v := policyBinding.(type) { case string: @@ -203,6 +200,7 @@ func extractPolicyBinding(policyBinding interface{}) (string, error) { return "", fmt.Errorf("unsupported policy binding type") } } + func verifyAndParsePolicy(ctx context.Context, requestBody *RequestBody, k []byte, logger logger.Logger) (*Policy, error) { actualHMAC, err := generateHMACDigest(ctx, []byte(requestBody.Policy), k, logger) if err != nil { @@ -246,7 +244,7 @@ func verifyAndParsePolicy(ctx context.Context, requestBody *RequestBody, k []byt } func getEntityInfo(ctx context.Context, logger *logger.Logger) (*entityInfo, error) { - var info = new(entityInfo) + info := new(entityInfo) token := auth.GetAccessTokenFromContext(ctx, logger) if token == nil { @@ -269,10 +267,11 @@ func getEntityInfo(ctx context.Context, logger *logger.Logger) (*entityInfo, err return info, nil } -func (p *Provider) Rewrap(ctx context.Context, in *kaspb.RewrapRequest) (*kaspb.RewrapResponse, error) { +func (p *Provider) Rewrap(ctx context.Context, req *connect.Request[kaspb.RewrapRequest]) (*connect.Response[kaspb.RewrapResponse], error) { + in := req.Msg p.Logger.DebugContext(ctx, "REWRAP") - body, err := extractSRTBody(ctx, in, *p.Logger) + body, err := extractSRTBody(ctx, req.Header(), in, *p.Logger) if err != nil { p.Logger.DebugContext(ctx, "unverifiable srt", "err", err) return nil, err @@ -295,13 +294,13 @@ func (p *Provider) Rewrap(ctx context.Context, in *kaspb.RewrapRequest) (*kaspb. p.Logger.ErrorContext(ctx, "rewrap nano", "err", err) } p.Logger.DebugContext(ctx, "rewrap nano", "rsp", rsp) - return rsp, err + return connect.NewResponse(rsp), err } rsp, err := p.tdf3Rewrap(ctx, body, entityInfo) if err != nil { p.Logger.ErrorContext(ctx, "rewrap tdf3", "err", err) } - return rsp, err + return connect.NewResponse(rsp), err } func (p *Provider) tdf3Rewrap(ctx context.Context, body *RequestBody, entity *entityInfo) (*kaspb.RewrapResponse, error) { diff --git a/service/kas/access/rewrap_test.go b/service/kas/access/rewrap_test.go index 74ad90290d..f75348a09d 100644 --- a/service/kas/access/rewrap_test.go +++ b/service/kas/access/rewrap_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "encoding/pem" "log/slog" + "net/http" "testing" "github.com/lestrrat-go/jwx/v2/jwa" @@ -154,7 +155,7 @@ func privateKey(t *testing.T) *rsa.PrivateKey { return k } -func publicKey(t *testing.T) *rsa.PublicKey { +func publicKeyTest(t *testing.T) *rsa.PublicKey { b, rest := pem.Decode([]byte(rsaPublic)) require.NotNil(t, b) assert.Empty(t, rest) @@ -298,7 +299,7 @@ func TestParseAndVerifyRequest(t *testing.T) { srt2 := makeRewrapBody(t, fauxPolicyBytes(t), true) badPolicySrt := makeRewrapBody(t, emptyPolicyBytes(), true) - var tests = []struct { + tests := []struct { name string body []byte goodDPoP bool @@ -322,7 +323,7 @@ func TestParseAndVerifyRequest(t *testing.T) { if tt.goodDPoP { key, err = jwk.FromRaw(entityPublicKey(t)) } else { - key, err = jwk.FromRaw(publicKey(t)) + key, err = jwk.FromRaw(publicKeyTest(t)) } require.NoError(t, err, "couldn't get JWK from key") err = key.Set(jwk.AlgorithmKey, jwa.RS256) // Check the error return value @@ -337,6 +338,7 @@ func TestParseAndVerifyRequest(t *testing.T) { verified, err := extractSRTBody( ctx, + http.Header{}, &kaspb.RewrapRequest{ SignedRequestToken: string(tt.body), }, @@ -375,6 +377,7 @@ func Test_SignedRequestBody_When_Bad_Signature_Expect_Failure(t *testing.T) { verified, err := extractSRTBody( ctx, + http.Header{}, &kaspb.RewrapRequest{ SignedRequestToken: string(makeRewrapBody(t, fauxPolicyBytes(t), false)), }, diff --git a/service/kas/kas.go b/service/kas/kas.go index 280a068ec1..6d42c5cbaa 100644 --- a/service/kas/kas.go +++ b/service/kas/kas.go @@ -1,26 +1,27 @@ package kas import ( - "context" "fmt" "log/slog" "net/url" "strings" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/mitchellh/mapstructure" kaspb "github.com/opentdf/platform/protocol/go/kas" + "github.com/opentdf/platform/protocol/go/kas/kasconnect" "github.com/opentdf/platform/service/internal/security" "github.com/opentdf/platform/service/kas/access" "github.com/opentdf/platform/service/pkg/serviceregistry" ) -func NewRegistration() *serviceregistry.Service[access.Provider] { - return &serviceregistry.Service[access.Provider]{ - ServiceOptions: serviceregistry.ServiceOptions[access.Provider]{ - Namespace: "kas", - ServiceDesc: &kaspb.AccessService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*access.Provider, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[kasconnect.AccessServiceHandler] { + return &serviceregistry.Service[kasconnect.AccessServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[kasconnect.AccessServiceHandler]{ + Namespace: "kas", + ServiceDesc: &kaspb.AccessService_ServiceDesc, + ConnectRPCFunc: kasconnect.NewAccessServiceHandler, + GRPCGateayFunc: kaspb.RegisterAccessServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (kasconnect.AccessServiceHandler, serviceregistry.HandlerServer) { // FIXME msg="mismatched key access url" keyAccessURL=http://localhost:9000 kasURL=https://:9000 hostWithPort := srp.OTDF.HTTPServer.Addr if strings.HasPrefix(hostWithPort, ":") { @@ -65,7 +66,7 @@ func NewRegistration() *serviceregistry.Service[access.Provider] { kasCfg.Keyring = append(kasCfg.Keyring, inferLegacyKeys(kasCfg.Keyring)...) } - p := access.Provider{ + p := &access.Provider{ URI: *kasURI, AttributeSvc: nil, CryptoProvider: srp.OTDF.CryptoProvider, @@ -80,9 +81,7 @@ func NewRegistration() *serviceregistry.Service[access.Provider] { srp.Logger.Error("failed to register kas readiness check", slog.String("error", err.Error())) } - return &p, func(ctx context.Context, mux *runtime.ServeMux) error { - return kaspb.RegisterAccessServiceHandlerServer(ctx, mux, &p) - } + return p, nil }, }, } diff --git a/service/kas/kas.proto b/service/kas/kas.proto index ee6555d946..8f0528d051 100644 --- a/service/kas/kas.proto +++ b/service/kas/kas.proto @@ -63,6 +63,7 @@ service AccessService { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { responses: {key: "200"} }; + option idempotency_level = NO_SIDE_EFFECTS; } // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME @@ -72,6 +73,7 @@ service AccessService { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { responses: {key: "200"} }; + option idempotency_level = NO_SIDE_EFFECTS; } rpc Rewrap(RewrapRequest) returns (RewrapResponse) { diff --git a/service/logger/audit/contextServerInterceptor.go b/service/logger/audit/contextServerInterceptor.go index 5c3e61a595..94984f8838 100644 --- a/service/logger/audit/contextServerInterceptor.go +++ b/service/logger/audit/contextServerInterceptor.go @@ -2,56 +2,58 @@ package audit import ( "context" + "net/http" + "connectrpc.com/connect" "github.com/google/uuid" sdkAudit "github.com/opentdf/platform/sdk/audit" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" ) // The audit unary server interceptor is a gRPC interceptor that adds metadata // to the context of incoming requests. This metadata is used to log audit // audit events. -func ContextServerInterceptor(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { - // Get metadata from the context - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, status.Error(codes.InvalidArgument, "missing metadata") +func ContextServerInterceptor() connect.UnaryInterceptorFunc { + interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { + return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + // Get metadata from the context + headers := req.Header() + + // Add request ID from existing header or create a new one + var requestID uuid.UUID + var err error + + requestIDFromMetadata := headers[http.CanonicalHeaderKey(sdkAudit.RequestIDHeaderKey.String())] + if len(requestIDFromMetadata) > 0 { + requestID, err = uuid.Parse(requestIDFromMetadata[0]) + if err != nil { + requestID = uuid.New() + } + } else { + requestID = uuid.New() + } + ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, requestID) + + // Get the request IP from the metadata header + requestIPFromMetadata := headers[http.CanonicalHeaderKey(sdkAudit.RequestIPHeaderKey.String())] + if len(requestIPFromMetadata) > 0 { + ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, requestIPFromMetadata[0]) + } + + // Get the actor ID from the metadata header + actorIDFromMetadata := headers[http.CanonicalHeaderKey(sdkAudit.ActorIDHeaderKey.String())] + if len(actorIDFromMetadata) > 0 { + ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, actorIDFromMetadata[0]) + } + + // Sets the user agent header on the context if it is present in the metadata + userAgent := headers[http.CanonicalHeaderKey(sdkAudit.UserAgentHeaderKey.String())] + if len(userAgent) > 0 { + ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, userAgent[0]) + } + + return next(ctx, req) + }) } - // Add request ID from existing header or create a new one - var requestID uuid.UUID - var err error - requestIDFromMetadata := md[string(sdkAudit.RequestIDHeaderKey)] - if len(requestIDFromMetadata) > 0 { - requestID, err = uuid.Parse(requestIDFromMetadata[0]) - if err != nil { - requestID = uuid.New() - } - } else { - requestID = uuid.New() - } - ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, requestID) - - // Get the request IP from the metadata header - requestIPFromMetadata := md[string(sdkAudit.RequestIPHeaderKey)] - if len(requestIPFromMetadata) > 0 { - ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, requestIPFromMetadata[0]) - } - - // Get the actor ID from the metadata header - actorIDFromMetadata := md[string(sdkAudit.ActorIDHeaderKey)] - if len(actorIDFromMetadata) > 0 { - ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, actorIDFromMetadata[0]) - } - - // Sets the user agent header on the context if it is present in the metadata - userAgent := md[string(sdkAudit.UserAgentHeaderKey)] - if len(userAgent) > 0 { - ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, userAgent[0]) - } - - return handler(ctx, req) + return connect.UnaryInterceptorFunc(interceptor) } diff --git a/service/logger/audit/getDecision_test.go b/service/logger/audit/getDecision_test.go index a442128a02..9fcee5da3b 100644 --- a/service/logger/audit/getDecision_test.go +++ b/service/logger/audit/getDecision_test.go @@ -33,7 +33,6 @@ func TestCreateGetDecisionEventHappyPathSuccess(t *testing.T) { } event, err := CreateGetDecisionEvent(createTestContext(), params) - if err != nil { t.Fatalf("error creating get decision audit event: %v", err) } @@ -73,7 +72,7 @@ func TestCreateGetDecisionEventHappyPathSuccess(t *testing.T) { expectedClientInfo := eventClientInfo{ Platform: "authorization", UserAgent: TestUserAgent, - RequestIP: TestRequestIP, + RequestIP: TestRequestIP.String(), } if !reflect.DeepEqual(event.ClientInfo, expectedClientInfo) { t.Fatalf("event client info did not match expected: got %+v, want %+v", event.ClientInfo, expectedClientInfo) diff --git a/service/logger/audit/helpers_test.go b/service/logger/audit/helpers_test.go index 3b4aeebc6b..3cd0271fcf 100644 --- a/service/logger/audit/helpers_test.go +++ b/service/logger/audit/helpers_test.go @@ -2,29 +2,33 @@ package audit import ( "context" + "net" "testing" "time" "github.com/google/uuid" sdkAudit "github.com/opentdf/platform/sdk/audit" + "github.com/opentdf/platform/service/internal/server/realip" ) const ( - TestUserAgent = "test-user-agent" - TestActorID = "test-actor-id" - TestRequestIP = "192.168.1.1" + TestUserAgent = "test-user-agent" + TestActorID = "test-actor-id" + TestTDFFormat = "nano" TestAlgorithm = "rsa" TestPolicyBinding = "test-policy-binding" ) +var TestRequestIP = net.ParseIP("192.168.1.1") + var TestRequestID = uuid.New() func createTestContext() context.Context { ctx := context.Background() ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, TestRequestID) ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, TestUserAgent) - ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, TestRequestIP) + ctx = context.WithValue(ctx, realip.ClientIP{}, TestRequestIP) ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, TestActorID) return ctx } diff --git a/service/logger/audit/policy_test.go b/service/logger/audit/policy_test.go index 15bfca110a..d65c4fb0f1 100644 --- a/service/logger/audit/policy_test.go +++ b/service/logger/audit/policy_test.go @@ -42,7 +42,6 @@ func Test_CreatePolicyEvent_HappyPath(t *testing.T) { } event, err := CreatePolicyEvent(createTestContext(), true, params) - if err != nil { t.Fatalf("error creating policy audit event: %v", err) } @@ -74,7 +73,7 @@ func Test_CreatePolicyEvent_HappyPath(t *testing.T) { expectedClientInfo := eventClientInfo{ Platform: "policy", UserAgent: TestUserAgent, - RequestIP: TestRequestIP, + RequestIP: TestRequestIP.String(), } if !reflect.DeepEqual(event.ClientInfo, expectedClientInfo) { t.Fatalf("event client info did not match expected: got %+v, want %+v", event.ClientInfo, expectedClientInfo) @@ -99,7 +98,6 @@ func Test_CreatePolicyEvent_WithOriginal(t *testing.T) { } event, err := CreatePolicyEvent(createTestContext(), true, params) - if err != nil { t.Fatalf("error creating policy audit event: %v", err) } diff --git a/service/logger/audit/rewrap_test.go b/service/logger/audit/rewrap_test.go index 4a1570a5cd..6fa36b482c 100644 --- a/service/logger/audit/rewrap_test.go +++ b/service/logger/audit/rewrap_test.go @@ -28,7 +28,6 @@ func TestCreateRewrapAuditEventHappyPath(t *testing.T) { } event, err := CreateRewrapAuditEvent(createTestContext(), params) - if err != nil { t.Fatalf("error creating rewrap audit event: %v", err) } @@ -75,7 +74,7 @@ func TestCreateRewrapAuditEventHappyPath(t *testing.T) { expectedClientInfo := eventClientInfo{ Platform: "kas", UserAgent: TestUserAgent, - RequestIP: TestRequestIP, + RequestIP: TestRequestIP.String(), } if !reflect.DeepEqual(event.ClientInfo, expectedClientInfo) { t.Fatalf("event client info did not match expected: got %+v, want %+v", event.ClientInfo, expectedClientInfo) diff --git a/service/logger/audit/utils.go b/service/logger/audit/utils.go index 6929eac998..fc3880c157 100644 --- a/service/logger/audit/utils.go +++ b/service/logger/audit/utils.go @@ -5,8 +5,8 @@ import ( "log/slog" "github.com/google/uuid" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip" sdkAudit "github.com/opentdf/platform/sdk/audit" + "github.com/opentdf/platform/service/internal/server/realip" ) // Common Strings @@ -155,14 +155,9 @@ func getContextValue(ctx context.Context, key sdkAudit.ContextKey) string { // can pass the custom X-Forwarded-Request-IP header for internal requests. If // that is not present, it falls back to the realip package. func getRequestIPFromContext(ctx context.Context) string { - requestIPFromContextKey, isOK := ctx.Value(sdkAudit.RequestIPContextKey).(string) - if isOK { - return requestIPFromContextKey - } - - requestIPFromRealip, ipOK := realip.FromContext(ctx) - if ipOK { - return requestIPFromRealip.String() + ip := realip.FromContext(ctx) + if ip.String() != "" && ip.String() != "" { + return ip.String() } return defaultNone diff --git a/service/logger/audit/utils_test.go b/service/logger/audit/utils_test.go index 1d0c755746..b87d311472 100644 --- a/service/logger/audit/utils_test.go +++ b/service/logger/audit/utils_test.go @@ -4,23 +4,25 @@ import ( "context" "fmt" "log/slog" + "net" "testing" "github.com/google/uuid" sdkAudit "github.com/opentdf/platform/sdk/audit" + "github.com/opentdf/platform/service/internal/server/realip" ) func TestGetAuditDataFromContextHappyPath(t *testing.T) { ctx := context.Background() testRequestID := uuid.New() testUserAgent := "test-user-agent" - testRequestIP := "192.168.0.1" + testRequestIP := net.ParseIP("192.168.0.1") testActorID := "test-actor-id" // Set relevant context keys ctx = context.WithValue(ctx, sdkAudit.RequestIDContextKey, testRequestID) ctx = context.WithValue(ctx, sdkAudit.UserAgentContextKey, testUserAgent) - ctx = context.WithValue(ctx, sdkAudit.RequestIPContextKey, testRequestIP) + ctx = context.WithValue(ctx, realip.ClientIP{}, testRequestIP) ctx = context.WithValue(ctx, sdkAudit.ActorIDContextKey, testActorID) slog.Info(fmt.Sprintf("Test: %v", ctx.Value(sdkAudit.RequestIDContextKey))) @@ -35,7 +37,7 @@ func TestGetAuditDataFromContextHappyPath(t *testing.T) { t.Fatalf("UserAgent did not match: %v", auditData.UserAgent) } - if auditData.RequestIP != testRequestIP { + if auditData.RequestIP != testRequestIP.String() { t.Fatalf("RequestIP did not match: %v", auditData.RequestIP) } @@ -65,6 +67,7 @@ func TestGetAuditDataFromContextDefaultsPath(t *testing.T) { t.Fatalf("ActorID did not match: %v", auditData.ActorID) } } + func TestGetAuditDataFromContextWithNoKeys(t *testing.T) { ctx := context.Background() auditData := GetAuditDataFromContext(ctx) @@ -85,6 +88,7 @@ func TestGetAuditDataFromContextWithNoKeys(t *testing.T) { t.Fatalf("ActorID did not match: %v", auditData.ActorID) } } + func TestGetAuditDataFromContextWithPartialKeys(t *testing.T) { ctx := context.Background() testUserAgent := "partial-user-agent" diff --git a/service/pkg/db/errors.go b/service/pkg/db/errors.go index 0299b7a435..49188f14dd 100644 --- a/service/pkg/db/errors.go +++ b/service/pkg/db/errors.go @@ -6,11 +6,10 @@ import ( "log/slog" "strings" + "connectrpc.com/connect" "github.com/jackc/pgerrcode" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) var ( @@ -104,28 +103,28 @@ func StatusifyError(err error, fallbackErr string, log ...any) error { l := append([]any{"error", err}, log...) if errors.Is(err, ErrUniqueConstraintViolation) { slog.Error(ErrTextConflict, l...) - return status.Error(codes.AlreadyExists, ErrTextConflict) + return connect.NewError(connect.CodeAlreadyExists, errors.New(ErrTextConflict)) } if errors.Is(err, ErrNotFound) { slog.Error(ErrTextNotFound, l...) - return status.Error(codes.NotFound, ErrTextNotFound) + return connect.NewError(connect.CodeNotFound, errors.New(ErrTextNotFound)) } if errors.Is(err, ErrForeignKeyViolation) { slog.Error(ErrTextRelationInvalid, l...) - return status.Error(codes.InvalidArgument, ErrTextRelationInvalid) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextRelationInvalid)) } if errors.Is(err, ErrEnumValueInvalid) { slog.Error(ErrTextEnumValueInvalid, l...) - return status.Error(codes.InvalidArgument, ErrTextEnumValueInvalid) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextEnumValueInvalid)) } if errors.Is(err, ErrUUIDInvalid) { slog.Error(ErrTextUUIDInvalid, l...) - return status.Error(codes.InvalidArgument, ErrTextUUIDInvalid) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextUUIDInvalid)) } if errors.Is(err, ErrRestrictViolation) { slog.Error(ErrTextRestrictViolation, l...) - return status.Error(codes.InvalidArgument, ErrTextRestrictViolation) + return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrTextRestrictViolation)) } slog.Error(err.Error(), l...) - return status.Error(codes.Internal, fallbackErr) + return connect.NewError(connect.CodeInternal, errors.New(fallbackErr)) } diff --git a/service/pkg/server/services.go b/service/pkg/server/services.go index 14d4e8f602..8760a5fbd8 100644 --- a/service/pkg/server/services.go +++ b/service/pkg/server/services.go @@ -21,6 +21,8 @@ import ( "github.com/opentdf/platform/service/pkg/serviceregistry" "github.com/opentdf/platform/service/policy" wellknown "github.com/opentdf/platform/service/wellknownconfiguration" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) const ( @@ -163,20 +165,29 @@ func startServices(ctx context.Context, cfg config.Config, otdf *server.OpenTDFS if err != nil { return err } - // Register the service with the gRPC server - if err := svc.RegisterGRPCServer(otdf.GRPCServer); err != nil { - return err + + // Register Connect RPC Services + if err := svc.RegisterConnectRPCServiceHandler(ctx, otdf.ConnectRPC); err != nil { + logger.Info("service did not register a connect-rpc handler", slog.String("namespace", ns)) } - // Register the service with in process gRPC server - if err := svc.RegisterGRPCServer(otdf.GRPCInProcess.GetGrpcServer()); err != nil { - return err + // Register In Process Connect RPC Services + if err := svc.RegisterConnectRPCServiceHandler(ctx, otdf.ConnectRPCInProcess.ConnectRPC); err != nil { + logger.Info("service did not register a connect-rpc handler", slog.String("namespace", ns)) } - // Register the service with the gRPC gateway - if err := svc.RegisterHTTPServer(ctx, otdf.Mux); err != nil { - logger.Error("failed to register service to grpc gateway", slog.String("namespace", ns), slog.String("error", err.Error())) - return err + // Register GRPC Gateway + grpcGatewayDialOptions := make([]grpc.DialOption, 0) + if !cfg.Server.TLS.Enabled { + grpcGatewayDialOptions = append(grpcGatewayDialOptions, grpc.WithTransportCredentials(insecure.NewCredentials())) + } + if err := svc.RegisterGRPCGatewayHandler(ctx, otdf.GRPCGatewayMux, fmt.Sprintf("localhost:%d", cfg.Server.Port), grpcGatewayDialOptions); err != nil { + logger.Info("service did not register a grpc gateway handler", slog.String("namespace", ns)) + } + + // Register Extra Handlers + if err := svc.RegisterHTTPHandlers(ctx, otdf.GRPCGatewayMux); err != nil { + logger.Info("service did not register extra http handlers", slog.String("namespace", ns)) } logger.Info( diff --git a/service/pkg/server/services_test.go b/service/pkg/server/services_test.go index 1f9037f400..97248da3a7 100644 --- a/service/pkg/server/services_test.go +++ b/service/pkg/server/services_test.go @@ -59,10 +59,10 @@ func mockTestServiceRegistry(opts mockTestServiceOptions) (serviceregistry.IServ ServiceName: serviceName, HandlerType: serviceHandlerType, }, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*TestService, serviceregistry.HandlerServer) { - var ts *TestService + RegisterFunc: func(srp serviceregistry.RegistrationParams) (TestService, serviceregistry.HandlerServer) { + var ts TestService var ok bool - if ts, ok = opts.serviceObject.(*TestService); !ok { + if ts, ok = opts.serviceObject.(TestService); !ok { panic("serviceObject is not a TestService") } return ts, func(ctx context.Context, mux *runtime.ServeMux) error { @@ -196,7 +196,7 @@ func (suite *ServiceTestSuite) TestStartServicesWithVariousCases() { // Test service which will be enabled registerTest, testSpy := mockTestServiceRegistry(mockTestServiceOptions{ - serviceObject: &TestService{}, + serviceObject: TestService{}, }) err := registry.RegisterService(registerTest, "test") suite.Require().NoError(err) diff --git a/service/pkg/server/start.go b/service/pkg/server/start.go index 8a82dec64e..dbbdf190b9 100644 --- a/service/pkg/server/start.go +++ b/service/pkg/server/start.go @@ -156,7 +156,7 @@ func Start(f ...StartOptions) error { if slices.Contains(cfg.Mode, "all") || slices.Contains(cfg.Mode, "core") { // Use IPC for the SDK client sdkOptions = append(sdkOptions, sdk.WithIPC()) - sdkOptions = append(sdkOptions, sdk.WithCustomCoreConnection(otdf.GRPCInProcess.Conn())) + sdkOptions = append(sdkOptions, sdk.WithCustomCoreConnection(otdf.ConnectRPCInProcess.Conn())) client, err = sdk.New("", sdkOptions...) if err != nil { diff --git a/service/pkg/server/start_test.go b/service/pkg/server/start_test.go index 5ab8ed3144..db66b50b28 100644 --- a/service/pkg/server/start_test.go +++ b/service/pkg/server/start_test.go @@ -99,7 +99,7 @@ func (suite *StartTestSuite) Test_Start_When_Extra_Service_Registered_Expect_Res require.NoError(t, err) // Register Test Service - ts := &TestService{} + ts := TestService{} registerTestService, _ := mockTestServiceRegistry(mockTestServiceOptions{ serviceObject: ts, serviceHandler: func(_ context.Context, mux *runtime.ServeMux) error { diff --git a/service/pkg/serviceregistry/serviceregistry.go b/service/pkg/serviceregistry/serviceregistry.go index 2d9ca082ed..a00218a60c 100644 --- a/service/pkg/serviceregistry/serviceregistry.go +++ b/service/pkg/serviceregistry/serviceregistry.go @@ -9,9 +9,9 @@ import ( "slices" "connectrpc.com/connect" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/opentdf/platform/sdk" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/opentdf/platform/service/internal/server" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/db" @@ -51,7 +51,7 @@ type RegistrationParams struct { } type ( HandlerServer func(ctx context.Context, mux *runtime.ServeMux) error - RegisterFunc[S any] func(RegistrationParams) (Impl *S, HandlerServer HandlerServer) + RegisterFunc[S any] func(RegistrationParams) (impl S, HandlerServer HandlerServer) ) // DBRegister is a struct that holds the information needed to register a service with a database @@ -72,15 +72,16 @@ type IService interface { Start(ctx context.Context, params RegistrationParams) error IsStarted() bool Shutdown() error - RegisterGRPCServer(server *grpc.Server) error - RegisterHTTPServer(ctx context.Context, mux *runtime.ServeMux) error + RegisterConnectRPCServiceHandler(context.Context, *server.ConnectRPC) error + RegisterGRPCGatewayHandler(context.Context, *runtime.ServeMux, string, []grpc.DialOption) error + RegisterHTTPHandlers(context.Context, *runtime.ServeMux) error } // Service is a struct that holds the registration information for a service as well as the state // of the service within the instance of the platform. type Service[S any] struct { // Registration - impl *S + impl S // Started is a flag that indicates whether the service has been started Started bool // Close is a function that can be called to close the service @@ -97,10 +98,13 @@ type ServiceOptions[S any] struct { // but at minimum, the ServiceName field must be set ServiceDesc *grpc.ServiceDesc // RegisterFunc is the function that will be called to register the service - RegisterFunc RegisterFunc[S] + RegisterFunc RegisterFunc[S] + // HTTPHandlerFunc is the function that will be called to register extra http handlers httpHandlerFunc HandlerServer // ConnectRPCServiceHandler is the function that will be called to register the service with the ConnectRPCFunc func(S, ...connect.HandlerOption) (string, http.Handler) + // Deprecated: Registers a gRPC service with the gRPC gateway + GRPCGateayFunc func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) // DB is optional and used to register the service with a database DB DBRegister } @@ -155,14 +159,13 @@ func (s *Service[S]) Start(ctx context.Context, params RegistrationParams) error return nil } -// RegisterGRPCServer registers the gRPC server with the service implementation. -// It checks if the service implementation is registered and then registers the service with the server. -// It returns an error if the service implementation is not registered. -func (s *Service[S]) RegisterGRPCServer(server *grpc.Server) error { - if s.impl == nil { - return fmt.Errorf("service did not register an implementation") +func (s Service[S]) RegisterConnectRPCServiceHandler(_ context.Context, connectRPC *server.ConnectRPC) error { + if s.ConnectRPCFunc == nil { + return fmt.Errorf("service did not register a handler") } - server.RegisterService(s.ServiceDesc, s.impl) + connectRPC.ServiceReflection = append(connectRPC.ServiceReflection, s.GetServiceDesc().ServiceName) + path, handler := s.ConnectRPCFunc(s.impl, connectRPC.Interceptors...) + connectRPC.Mux.Handle(path, handler) return nil } @@ -171,13 +174,25 @@ func (s *Service[S]) RegisterGRPCServer(server *grpc.Server) error { // RegisterHTTPServer registers an HTTP server with the service. // It takes a context, a ServeMux, and an implementation function as parameters. // If the service did not register a handler, it returns an error. -func (s *Service[S]) RegisterHTTPServer(ctx context.Context, mux *runtime.ServeMux) error { +func (s *Service[S]) RegisterHTTPHandlers(ctx context.Context, mux *runtime.ServeMux) error { if s.httpHandlerFunc == nil { - return fmt.Errorf("service did not register a handler") + return fmt.Errorf("service did not register any handlers") } return s.httpHandlerFunc(ctx, mux) } +// Deprecated: RegisterConnectRPCServiceHandler is deprecated and should not be used going forward. +// We will be looking onto other alternatives like bufconnect to replace this. +// RegisterConnectRPCServiceHandler registers an HTTP server with the service. +// It takes a context, a ServeMux, and an implementation function as parameters. +// If the service did not register a handler, it returns an error. +func (s Service[S]) RegisterGRPCGatewayHandler(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error { + if s.GRPCGateayFunc == nil { + return fmt.Errorf("service did not register a handler") + } + return s.GRPCGateayFunc(ctx, mux, endpoint, opts) +} + // namespace represents a namespace in the service registry. type Namespace struct { Mode string diff --git a/service/policy/attributes/attributes.go b/service/policy/attributes/attributes.go index c3d31aa836..8ca210ac0d 100644 --- a/service/policy/attributes/attributes.go +++ b/service/policy/attributes/attributes.go @@ -5,9 +5,10 @@ import ( "fmt" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/attributes" + "github.com/opentdf/platform/protocol/go/policy/attributes/attributesconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -16,31 +17,30 @@ import ( ) type AttributesService struct { //nolint:revive // AttributesService is a valid name for this struct - attributes.UnimplementedAttributesServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[AttributesService] { - return &serviceregistry.Service[AttributesService]{ - ServiceOptions: serviceregistry.ServiceOptions[AttributesService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &attributes.AttributesService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*AttributesService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[attributesconnect.AttributesServiceHandler] { + return &serviceregistry.Service[attributesconnect.AttributesServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[attributesconnect.AttributesServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &attributes.AttributesService_ServiceDesc, + ConnectRPCFunc: attributesconnect.NewAttributesServiceHandler, + GRPCGateayFunc: attributes.RegisterAttributesServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (attributesconnect.AttributesServiceHandler, serviceregistry.HandlerServer) { as := &AttributesService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return as, func(ctx context.Context, mux *runtime.ServeMux) error { - return attributes.RegisterAttributesServiceHandlerServer(ctx, mux, as) - } + return as, nil }, }, } } func (s AttributesService) CreateAttribute(ctx context.Context, - req *attributes.CreateAttributeRequest, -) (*attributes.CreateAttributeResponse, error) { - s.logger.Debug("creating new attribute definition", slog.String("name", req.GetName())) + req *connect.Request[attributes.CreateAttributeRequest], +) (*connect.Response[attributes.CreateAttributeResponse], error) { + s.logger.Debug("creating new attribute definition", slog.String("name", req.Msg.GetName())) rsp := &attributes.CreateAttributeResponse{} auditParams := audit.PolicyEventParams{ @@ -48,27 +48,27 @@ func (s AttributesService) CreateAttribute(ctx context.Context, ActionType: audit.ActionTypeCreate, } - item, err := s.dbClient.CreateAttribute(ctx, req) + item, err := s.dbClient.CreateAttribute(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attribute", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attribute", req.Msg.String())) } - s.logger.Debug("created new attribute definition", slog.String("name", req.GetName())) + s.logger.Debug("created new attribute definition", slog.String("name", req.Msg.GetName())) auditParams.ObjectID = item.GetId() auditParams.Original = item s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) rsp.Attribute = item - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) ListAttributes(ctx context.Context, - req *attributes.ListAttributesRequest, -) (*attributes.ListAttributesResponse, error) { - state := policydb.GetDBStateTypeTransformedEnum(req.GetState()) - namespace := req.GetNamespace() + req *connect.Request[attributes.ListAttributesRequest], +) (*connect.Response[attributes.ListAttributesResponse], error) { + state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) + namespace := req.Msg.GetNamespace() s.logger.Debug("listing attribute definitions", slog.String("state", state)) rsp := &attributes.ListAttributesResponse{} @@ -78,43 +78,43 @@ func (s *AttributesService) ListAttributes(ctx context.Context, } rsp.Attributes = list - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) GetAttribute(ctx context.Context, - req *attributes.GetAttributeRequest, -) (*attributes.GetAttributeResponse, error) { + req *connect.Request[attributes.GetAttributeRequest], +) (*connect.Response[attributes.GetAttributeResponse], error) { rsp := &attributes.GetAttributeResponse{} - item, err := s.dbClient.GetAttribute(ctx, req.GetId()) + item, err := s.dbClient.GetAttribute(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } rsp.Attribute = item - return rsp, err + return connect.NewResponse(rsp), err } func (s *AttributesService) GetAttributeValuesByFqns(ctx context.Context, - req *attributes.GetAttributeValuesByFqnsRequest, -) (*attributes.GetAttributeValuesByFqnsResponse, error) { + req *connect.Request[attributes.GetAttributeValuesByFqnsRequest], +) (*connect.Response[attributes.GetAttributeValuesByFqnsResponse], error) { rsp := &attributes.GetAttributeValuesByFqnsResponse{} - fqnsToAttributes, err := s.dbClient.GetAttributesByValueFqns(ctx, req) + fqnsToAttributes, err := s.dbClient.GetAttributesByValueFqns(ctx, req.Msg) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("fqns", fmt.Sprintf("%v", req.GetFqns()))) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("fqns", fmt.Sprintf("%v", req.Msg.GetFqns()))) } rsp.FqnAttributeValues = fqnsToAttributes - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) UpdateAttribute(ctx context.Context, - req *attributes.UpdateAttributeRequest, -) (*attributes.UpdateAttributeResponse, error) { + req *connect.Request[attributes.UpdateAttributeRequest], +) (*connect.Response[attributes.UpdateAttributeResponse], error) { rsp := &attributes.UpdateAttributeResponse{} - attributeID := req.GetId() + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, ObjectType: audit.ObjectTypeAttributeDefinition, @@ -127,10 +127,10 @@ func (s *AttributesService) UpdateAttribute(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", attributeID)) } - updated, err := s.dbClient.UpdateAttribute(ctx, attributeID, req) + updated, err := s.dbClient.UpdateAttribute(ctx, attributeID, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("attribute", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("attribute", req.Msg.String())) } auditParams.Original = original @@ -141,15 +141,15 @@ func (s *AttributesService) UpdateAttribute(ctx context.Context, Id: attributeID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s *AttributesService) DeactivateAttribute(ctx context.Context, - req *attributes.DeactivateAttributeRequest, -) (*attributes.DeactivateAttributeResponse, error) { + req *connect.Request[attributes.DeactivateAttributeRequest], +) (*connect.Response[attributes.DeactivateAttributeResponse], error) { rsp := &attributes.DeactivateAttributeResponse{} - attributeID := req.GetId() + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ObjectType: audit.ObjectTypeAttributeDefinition, ActionType: audit.ActionTypeUpdate, @@ -175,60 +175,67 @@ func (s *AttributesService) DeactivateAttribute(ctx context.Context, rsp.Attribute = &policy.Attribute{ Id: attributeID, } - return rsp, nil + return connect.NewResponse(rsp), nil } /// /// Attribute Values /// -func (s *AttributesService) CreateAttributeValue(ctx context.Context, req *attributes.CreateAttributeValueRequest) (*attributes.CreateAttributeValueResponse, error) { +func (s *AttributesService) CreateAttributeValue(ctx context.Context, req *connect.Request[attributes.CreateAttributeValueRequest]) (*connect.Response[attributes.CreateAttributeValueResponse], error) { + rsp := &attributes.CreateAttributeValueResponse{} + auditParams := audit.PolicyEventParams{ ObjectType: audit.ObjectTypeAttributeValue, ActionType: audit.ActionTypeCreate, } - item, err := s.dbClient.CreateAttributeValue(ctx, req.GetAttributeId(), req) + item, err := s.dbClient.CreateAttributeValue(ctx, req.Msg.GetAttributeId(), req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeId", req.GetAttributeId()), slog.String("value", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeId", req.Msg.GetAttributeId()), slog.String("value", req.Msg.String())) } auditParams.ObjectID = item.GetId() auditParams.Original = item s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.CreateAttributeValueResponse{ - Value: item, - }, nil + rsp.Value = item + return connect.NewResponse(rsp), nil } -func (s *AttributesService) ListAttributeValues(ctx context.Context, req *attributes.ListAttributeValuesRequest) (*attributes.ListAttributeValuesResponse, error) { - state := policydb.GetDBStateTypeTransformedEnum(req.GetState()) - s.logger.Debug("listing attribute values", slog.String("attributeId", req.GetAttributeId()), slog.String("state", state)) - list, err := s.dbClient.ListAttributeValues(ctx, req.GetAttributeId(), state) +func (s *AttributesService) ListAttributeValues(ctx context.Context, req *connect.Request[attributes.ListAttributeValuesRequest]) (*connect.Response[attributes.ListAttributeValuesResponse], error) { + rsp := &attributes.ListAttributeValuesResponse{} + + state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) + s.logger.Debug("listing attribute values", slog.String("attributeId", req.Msg.GetAttributeId()), slog.String("state", state)) + list, err := s.dbClient.ListAttributeValues(ctx, req.Msg.GetAttributeId(), state) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.String("attributeId", req.GetAttributeId())) + return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.String("attributeId", req.Msg.GetAttributeId())) } - return &attributes.ListAttributeValuesResponse{ - Values: list, - }, nil + rsp.Values = list + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) GetAttributeValue(ctx context.Context, req *attributes.GetAttributeValueRequest) (*attributes.GetAttributeValueResponse, error) { - item, err := s.dbClient.GetAttributeValue(ctx, req.GetId()) +func (s *AttributesService) GetAttributeValue(ctx context.Context, req *connect.Request[attributes.GetAttributeValueRequest]) (*connect.Response[attributes.GetAttributeValueResponse], error) { + rsp := &attributes.GetAttributeValueResponse{} + + item, err := s.dbClient.GetAttributeValue(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &attributes.GetAttributeValueResponse{ - Value: item, - }, nil + rsp.Value = item + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) UpdateAttributeValue(ctx context.Context, req *attributes.UpdateAttributeValueRequest) (*attributes.UpdateAttributeValueResponse, error) { - attributeID := req.GetId() +func (s *AttributesService) UpdateAttributeValue(ctx context.Context, req *connect.Request[attributes.UpdateAttributeValueRequest]) (*connect.Response[attributes.UpdateAttributeValueResponse], error) { + rsp := &attributes.UpdateAttributeValueResponse{} + + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, ObjectType: audit.ObjectTypeAttributeValue, @@ -241,25 +248,27 @@ func (s *AttributesService) UpdateAttributeValue(ctx context.Context, req *attri return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", attributeID)) } - updated, err := s.dbClient.UpdateAttributeValue(ctx, req) + updated, err := s.dbClient.UpdateAttributeValue(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("value", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("value", req.Msg.String())) } auditParams.Original = original auditParams.Updated = updated s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.UpdateAttributeValueResponse{ - Value: &policy.Value{ - Id: attributeID, - }, - }, nil + rsp.Value = &policy.Value{ + Id: attributeID, + } + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *attributes.DeactivateAttributeValueRequest) (*attributes.DeactivateAttributeValueResponse, error) { - attributeID := req.GetId() +func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *connect.Request[attributes.DeactivateAttributeValueRequest]) (*connect.Response[attributes.DeactivateAttributeValueResponse], error) { + rsp := &attributes.DeactivateAttributeValueResponse{} + + attributeID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ObjectType: audit.ObjectTypeAttributeValue, ActionType: audit.ActionTypeDelete, @@ -282,83 +291,91 @@ func (s *AttributesService) DeactivateAttributeValue(ctx context.Context, req *a auditParams.Updated = updated s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.DeactivateAttributeValueResponse{ - Value: updated, - }, nil + rsp.Value = updated + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) AssignKeyAccessServerToAttribute(ctx context.Context, req *attributes.AssignKeyAccessServerToAttributeRequest) (*attributes.AssignKeyAccessServerToAttributeResponse, error) { +func (s *AttributesService) AssignKeyAccessServerToAttribute(ctx context.Context, req *connect.Request[attributes.AssignKeyAccessServerToAttributeRequest]) (*connect.Response[attributes.AssignKeyAccessServerToAttributeResponse], error) { + rsp := &attributes.AssignKeyAccessServerToAttributeResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeKasAttributeDefinitionAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetAttributeKeyAccessServer().GetAttributeId(), req.GetAttributeKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetAttributeKeyAccessServer().GetAttributeId(), req.Msg.GetAttributeKeyAccessServer().GetKeyAccessServerId()), } - attributeKas, err := s.dbClient.AssignKeyAccessServerToAttribute(ctx, req.GetAttributeKeyAccessServer()) + attributeKas, err := s.dbClient.AssignKeyAccessServerToAttribute(ctx, req.Msg.GetAttributeKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeKas", req.GetAttributeKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeKas", req.Msg.GetAttributeKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.AssignKeyAccessServerToAttributeResponse{ - AttributeKeyAccessServer: attributeKas, - }, nil + rsp.AttributeKeyAccessServer = attributeKas + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) RemoveKeyAccessServerFromAttribute(ctx context.Context, req *attributes.RemoveKeyAccessServerFromAttributeRequest) (*attributes.RemoveKeyAccessServerFromAttributeResponse, error) { +func (s *AttributesService) RemoveKeyAccessServerFromAttribute(ctx context.Context, req *connect.Request[attributes.RemoveKeyAccessServerFromAttributeRequest]) (*connect.Response[attributes.RemoveKeyAccessServerFromAttributeResponse], error) { + rsp := &attributes.RemoveKeyAccessServerFromAttributeResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasAttributeDefinitionAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetAttributeKeyAccessServer().GetAttributeId(), req.GetAttributeKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetAttributeKeyAccessServer().GetAttributeId(), req.Msg.GetAttributeKeyAccessServer().GetKeyAccessServerId()), } - attributeKas, err := s.dbClient.RemoveKeyAccessServerFromAttribute(ctx, req.GetAttributeKeyAccessServer()) + attributeKas, err := s.dbClient.RemoveKeyAccessServerFromAttribute(ctx, req.Msg.GetAttributeKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeKas", req.GetAttributeKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeKas", req.Msg.GetAttributeKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.RemoveKeyAccessServerFromAttributeResponse{ - AttributeKeyAccessServer: attributeKas, - }, nil + rsp.AttributeKeyAccessServer = attributeKas + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) AssignKeyAccessServerToValue(ctx context.Context, req *attributes.AssignKeyAccessServerToValueRequest) (*attributes.AssignKeyAccessServerToValueResponse, error) { +func (s *AttributesService) AssignKeyAccessServerToValue(ctx context.Context, req *connect.Request[attributes.AssignKeyAccessServerToValueRequest]) (*connect.Response[attributes.AssignKeyAccessServerToValueResponse], error) { + rsp := &attributes.AssignKeyAccessServerToValueResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeKasAttributeValueAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetValueKeyAccessServer().GetValueId(), req.GetValueKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetValueKeyAccessServer().GetValueId(), req.Msg.GetValueKeyAccessServer().GetKeyAccessServerId()), } - valueKas, err := s.dbClient.AssignKeyAccessServerToValue(ctx, req.GetValueKeyAccessServer()) + valueKas, err := s.dbClient.AssignKeyAccessServerToValue(ctx, req.Msg.GetValueKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeValueKas", req.GetValueKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("attributeValueKas", req.Msg.GetValueKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.AssignKeyAccessServerToValueResponse{ - ValueKeyAccessServer: valueKas, - }, nil + rsp.ValueKeyAccessServer = valueKas + + return connect.NewResponse(rsp), nil } -func (s *AttributesService) RemoveKeyAccessServerFromValue(ctx context.Context, req *attributes.RemoveKeyAccessServerFromValueRequest) (*attributes.RemoveKeyAccessServerFromValueResponse, error) { +func (s *AttributesService) RemoveKeyAccessServerFromValue(ctx context.Context, req *connect.Request[attributes.RemoveKeyAccessServerFromValueRequest]) (*connect.Response[attributes.RemoveKeyAccessServerFromValueResponse], error) { + rsp := &attributes.RemoveKeyAccessServerFromValueResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasAttributeValueAssignment, - ObjectID: fmt.Sprintf("%s-%s", req.GetValueKeyAccessServer().GetValueId(), req.GetValueKeyAccessServer().GetKeyAccessServerId()), + ObjectID: fmt.Sprintf("%s-%s", req.Msg.GetValueKeyAccessServer().GetValueId(), req.Msg.GetValueKeyAccessServer().GetKeyAccessServerId()), } - valueKas, err := s.dbClient.RemoveKeyAccessServerFromValue(ctx, req.GetValueKeyAccessServer()) + valueKas, err := s.dbClient.RemoveKeyAccessServerFromValue(ctx, req.Msg.GetValueKeyAccessServer()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeValueKas", req.GetValueKeyAccessServer().String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("attributeValueKas", req.Msg.GetValueKeyAccessServer().String())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &attributes.RemoveKeyAccessServerFromValueResponse{ - ValueKeyAccessServer: valueKas, - }, nil + rsp.ValueKeyAccessServer = valueKas + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/attributes/attributes.proto b/service/policy/attributes/attributes.proto index 2a339a67f3..6609d6ba2f 100644 --- a/service/policy/attributes/attributes.proto +++ b/service/policy/attributes/attributes.proto @@ -293,16 +293,20 @@ service AttributesService { *---------------------------------------*/ rpc ListAttributes(ListAttributesRequest) returns (ListAttributesResponse) { option (google.api.http) = {get: "/attributes"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc ListAttributeValues(ListAttributeValuesRequest) returns (ListAttributeValuesResponse) { option (google.api.http) = {get: "/attributes/*/values"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetAttribute(GetAttributeRequest) returns (GetAttributeResponse) { option (google.api.http) = {get: "/attributes/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetAttributeValuesByFqns(GetAttributeValuesByFqnsRequest) returns (GetAttributeValuesByFqnsResponse) { option (google.api.http) = {get: "/attributes/*/fqn"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateAttribute(CreateAttributeRequest) returns (CreateAttributeResponse) { diff --git a/service/policy/kasregistry/key_access_server_registry.go b/service/policy/kasregistry/key_access_server_registry.go index db821d1ac7..088996f217 100644 --- a/service/policy/kasregistry/key_access_server_registry.go +++ b/service/policy/kasregistry/key_access_server_registry.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" kasr "github.com/opentdf/platform/protocol/go/policy/kasregistry" + "github.com/opentdf/platform/protocol/go/policy/kasregistry/kasregistryconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,30 +16,31 @@ import ( ) type KeyAccessServerRegistry struct { - kasr.UnimplementedKeyAccessServerRegistryServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[KeyAccessServerRegistry] { - return &serviceregistry.Service[KeyAccessServerRegistry]{ - ServiceOptions: serviceregistry.ServiceOptions[KeyAccessServerRegistry]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &kasr.KeyAccessServerRegistryService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*KeyAccessServerRegistry, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[kasregistryconnect.KeyAccessServerRegistryServiceHandler] { + return &serviceregistry.Service[kasregistryconnect.KeyAccessServerRegistryServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[kasregistryconnect.KeyAccessServerRegistryServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &kasr.KeyAccessServerRegistryService_ServiceDesc, + ConnectRPCFunc: kasregistryconnect.NewKeyAccessServerRegistryServiceHandler, + GRPCGateayFunc: kasr.RegisterKeyAccessServerRegistryServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (kasregistryconnect.KeyAccessServerRegistryServiceHandler, serviceregistry.HandlerServer) { ksr := &KeyAccessServerRegistry{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return ksr, func(ctx context.Context, mux *runtime.ServeMux) error { - return kasr.RegisterKeyAccessServerRegistryServiceHandlerServer(ctx, mux, ksr) - } + return ksr, nil }, }, } } func (s KeyAccessServerRegistry) CreateKeyAccessServer(ctx context.Context, - req *kasr.CreateKeyAccessServerRequest, -) (*kasr.CreateKeyAccessServerResponse, error) { + req *connect.Request[kasr.CreateKeyAccessServerRequest], +) (*connect.Response[kasr.CreateKeyAccessServerResponse], error) { + rsp := &kasr.CreateKeyAccessServerResponse{} + s.logger.Debug("creating key access server") auditParams := audit.PolicyEventParams{ @@ -46,51 +48,57 @@ func (s KeyAccessServerRegistry) CreateKeyAccessServer(ctx context.Context, ObjectType: audit.ObjectTypeKasRegistry, } - ks, err := s.dbClient.CreateKeyAccessServer(ctx, req) + ks, err := s.dbClient.CreateKeyAccessServer(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("keyAccessServer", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("keyAccessServer", req.Msg.String())) } auditParams.ObjectID = ks.GetId() auditParams.Original = ks s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &kasr.CreateKeyAccessServerResponse{ - KeyAccessServer: ks, - }, nil + rsp.KeyAccessServer = ks + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) ListKeyAccessServers(ctx context.Context, - _ *kasr.ListKeyAccessServersRequest, -) (*kasr.ListKeyAccessServersResponse, error) { + _ *connect.Request[kasr.ListKeyAccessServersRequest], +) (*connect.Response[kasr.ListKeyAccessServersResponse], error) { + rsp := &kasr.ListKeyAccessServersResponse{} + keyAccessServers, err := s.dbClient.ListKeyAccessServers(ctx) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &kasr.ListKeyAccessServersResponse{ - KeyAccessServers: keyAccessServers, - }, nil + rsp.KeyAccessServers = keyAccessServers + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) GetKeyAccessServer(ctx context.Context, - req *kasr.GetKeyAccessServerRequest, -) (*kasr.GetKeyAccessServerResponse, error) { - keyAccessServer, err := s.dbClient.GetKeyAccessServer(ctx, req.GetId()) + req *connect.Request[kasr.GetKeyAccessServerRequest], +) (*connect.Response[kasr.GetKeyAccessServerResponse], error) { + rsp := &kasr.GetKeyAccessServerResponse{} + + keyAccessServer, err := s.dbClient.GetKeyAccessServer(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &kasr.GetKeyAccessServerResponse{ - KeyAccessServer: keyAccessServer, - }, nil + rsp.KeyAccessServer = keyAccessServer + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) UpdateKeyAccessServer(ctx context.Context, - req *kasr.UpdateKeyAccessServerRequest, -) (*kasr.UpdateKeyAccessServerResponse, error) { - kasID := req.GetId() + req *connect.Request[kasr.UpdateKeyAccessServerRequest], +) (*connect.Response[kasr.UpdateKeyAccessServerResponse], error) { + rsp := &kasr.UpdateKeyAccessServerResponse{} + + kasID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -104,56 +112,60 @@ func (s KeyAccessServerRegistry) UpdateKeyAccessServer(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", kasID)) } - updated, err := s.dbClient.UpdateKeyAccessServer(ctx, kasID, req) + updated, err := s.dbClient.UpdateKeyAccessServer(ctx, kasID, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", kasID), slog.String("keyAccessServer", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", kasID), slog.String("keyAccessServer", req.Msg.String())) } auditParams.Original = original auditParams.Updated = updated s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &kasr.UpdateKeyAccessServerResponse{ - KeyAccessServer: &policy.KeyAccessServer{ - Id: kasID, - }, - }, nil + rsp.KeyAccessServer = &policy.KeyAccessServer{ + Id: kasID, + } + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) DeleteKeyAccessServer(ctx context.Context, - req *kasr.DeleteKeyAccessServerRequest, -) (*kasr.DeleteKeyAccessServerResponse, error) { - kasID := req.GetId() + req *connect.Request[kasr.DeleteKeyAccessServerRequest], +) (*connect.Response[kasr.DeleteKeyAccessServerResponse], error) { + rsp := &kasr.DeleteKeyAccessServerResponse{} + + kasID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasRegistry, ObjectID: kasID, } - _, err := s.dbClient.DeleteKeyAccessServer(ctx, req.GetId()) + _, err := s.dbClient.DeleteKeyAccessServer(ctx, req.Msg.GetId()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", req.Msg.GetId())) } s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &kasr.DeleteKeyAccessServerResponse{ - KeyAccessServer: &policy.KeyAccessServer{ - Id: kasID, - }, - }, nil + rsp.KeyAccessServer = &policy.KeyAccessServer{ + Id: kasID, + } + + return connect.NewResponse(rsp), nil } func (s KeyAccessServerRegistry) ListKeyAccessServerGrants(ctx context.Context, - req *kasr.ListKeyAccessServerGrantsRequest, -) (*kasr.ListKeyAccessServerGrantsResponse, error) { - keyAccessServerGrants, err := s.dbClient.ListKeyAccessServerGrants(ctx, req.GetKasId(), req.GetKasUri(), req.GetKasName()) + req *connect.Request[kasr.ListKeyAccessServerGrantsRequest], +) (*connect.Response[kasr.ListKeyAccessServerGrantsResponse], error) { + rsp := &kasr.ListKeyAccessServerGrantsResponse{} + + keyAccessServerGrants, err := s.dbClient.ListKeyAccessServerGrants(ctx, req.Msg.GetKasId(), req.Msg.GetKasUri(), req.Msg.GetKasName()) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &kasr.ListKeyAccessServerGrantsResponse{ - Grants: keyAccessServerGrants, - }, nil + rsp.Grants = keyAccessServerGrants + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/kasregistry/key_access_server_registry.proto b/service/policy/kasregistry/key_access_server_registry.proto index ce0218ab73..109541944f 100644 --- a/service/policy/kasregistry/key_access_server_registry.proto +++ b/service/policy/kasregistry/key_access_server_registry.proto @@ -162,10 +162,12 @@ message ListKeyAccessServerGrantsResponse { service KeyAccessServerRegistryService { rpc ListKeyAccessServers(ListKeyAccessServersRequest) returns (ListKeyAccessServersResponse) { option (google.api.http) = {get: "/key-access-servers"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetKeyAccessServer(GetKeyAccessServerRequest) returns (GetKeyAccessServerResponse) { option (google.api.http) = {get: "/key-access-servers/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateKeyAccessServer(CreateKeyAccessServerRequest) returns (CreateKeyAccessServerResponse) { @@ -188,5 +190,6 @@ service KeyAccessServerRegistryService { rpc ListKeyAccessServerGrants(ListKeyAccessServerGrantsRequest) returns (ListKeyAccessServerGrantsResponse) { option (google.api.http) = {get: "/key-access-servers/grants"}; + option idempotency_level = NO_SIDE_EFFECTS; } } diff --git a/service/policy/namespaces/namespaces.go b/service/policy/namespaces/namespaces.go index f9ca32f53b..37cb539709 100644 --- a/service/policy/namespaces/namespaces.go +++ b/service/policy/namespaces/namespaces.go @@ -5,9 +5,10 @@ import ( "fmt" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/namespaces" + "github.com/opentdf/platform/protocol/go/policy/namespaces/namespacesconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -16,27 +17,26 @@ import ( ) type NamespacesService struct { //nolint:revive // NamespacesService is a valid name - namespaces.UnimplementedNamespaceServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[NamespacesService] { - return &serviceregistry.Service[NamespacesService]{ - ServiceOptions: serviceregistry.ServiceOptions[NamespacesService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &namespaces.NamespaceService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*NamespacesService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[namespacesconnect.NamespaceServiceHandler] { + return &serviceregistry.Service[namespacesconnect.NamespaceServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[namespacesconnect.NamespaceServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &namespaces.NamespaceService_ServiceDesc, + ConnectRPCFunc: namespacesconnect.NewNamespaceServiceHandler, + GRPCGateayFunc: namespaces.RegisterNamespaceServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (namespacesconnect.NamespaceServiceHandler, serviceregistry.HandlerServer) { ns := &NamespacesService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} if err := srp.RegisterReadinessCheck("policy", ns.IsReady); err != nil { srp.Logger.Error("failed to register policy readiness check", slog.String("error", err.Error())) } - return ns, func(ctx context.Context, mux *runtime.ServeMux) error { - return namespaces.RegisterNamespaceServiceHandlerServer(ctx, mux, ns) - } + return ns, nil }, }, } @@ -53,8 +53,8 @@ func (ns NamespacesService) IsReady(ctx context.Context) error { return nil } -func (ns NamespacesService) ListNamespaces(ctx context.Context, req *namespaces.ListNamespacesRequest) (*namespaces.ListNamespacesResponse, error) { - state := policydb.GetDBStateTypeTransformedEnum(req.GetState()) +func (ns NamespacesService) ListNamespaces(ctx context.Context, req *connect.Request[namespaces.ListNamespacesRequest]) (*connect.Response[namespaces.ListNamespacesResponse], error) { + state := policydb.GetDBStateTypeTransformedEnum(req.Msg.GetState()) ns.logger.Debug("listing namespaces", slog.String("state", state)) rsp := &namespaces.ListNamespacesResponse{} @@ -66,26 +66,26 @@ func (ns NamespacesService) ListNamespaces(ctx context.Context, req *namespaces. ns.logger.Debug("listed namespaces") rsp.Namespaces = list - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) GetNamespace(ctx context.Context, req *namespaces.GetNamespaceRequest) (*namespaces.GetNamespaceResponse, error) { - ns.logger.Debug("getting namespace", slog.String("id", req.GetId())) +func (ns NamespacesService) GetNamespace(ctx context.Context, req *connect.Request[namespaces.GetNamespaceRequest]) (*connect.Response[namespaces.GetNamespaceResponse], error) { + ns.logger.Debug("getting namespace", slog.String("id", req.Msg.GetId())) rsp := &namespaces.GetNamespaceResponse{} - namespace, err := ns.dbClient.GetNamespace(ctx, req.GetId()) + namespace, err := ns.dbClient.GetNamespace(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, "id", req.GetId()) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, "id", req.Msg.GetId()) } rsp.Namespace = namespace - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) CreateNamespace(ctx context.Context, req *namespaces.CreateNamespaceRequest) (*namespaces.CreateNamespaceResponse, error) { - ns.logger.Debug("creating new namespace", slog.String("name", req.GetName())) +func (ns NamespacesService) CreateNamespace(ctx context.Context, req *connect.Request[namespaces.CreateNamespaceRequest]) (*connect.Response[namespaces.CreateNamespaceResponse], error) { + ns.logger.Debug("creating new namespace", slog.String("name", req.Msg.GetName())) auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, @@ -93,24 +93,24 @@ func (ns NamespacesService) CreateNamespace(ctx context.Context, req *namespaces } rsp := &namespaces.CreateNamespaceResponse{} - n, err := ns.dbClient.CreateNamespace(ctx, req) + n, err := ns.dbClient.CreateNamespace(ctx, req.Msg) if err != nil { ns.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("name", req.GetName())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("name", req.Msg.GetName())) } auditParams.ObjectID = n.GetId() auditParams.Original = n ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - ns.logger.Debug("created new namespace", slog.String("name", req.GetName())) + ns.logger.Debug("created new namespace", slog.String("name", req.Msg.GetName())) rsp.Namespace = n - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *namespaces.UpdateNamespaceRequest) (*namespaces.UpdateNamespaceResponse, error) { - namespaceID := req.GetId() +func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *connect.Request[namespaces.UpdateNamespaceRequest]) (*connect.Response[namespaces.UpdateNamespaceResponse], error) { + namespaceID := req.Msg.GetId() ns.logger.Debug("updating namespace", slog.String("name", namespaceID)) rsp := &namespaces.UpdateNamespaceResponse{} @@ -126,7 +126,7 @@ func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *namespaces return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", namespaceID)) } - updated, err := ns.dbClient.UpdateNamespace(ctx, namespaceID, req) + updated, err := ns.dbClient.UpdateNamespace(ctx, namespaceID, req.Msg) if err != nil { ns.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", namespaceID)) @@ -141,11 +141,11 @@ func (ns NamespacesService) UpdateNamespace(ctx context.Context, req *namespaces rsp.Namespace = &policy.Namespace{ Id: namespaceID, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *namespaces.DeactivateNamespaceRequest) (*namespaces.DeactivateNamespaceResponse, error) { - namespaceID := req.GetId() +func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *connect.Request[namespaces.DeactivateNamespaceRequest]) (*connect.Response[namespaces.DeactivateNamespaceResponse], error) { + namespaceID := req.Msg.GetId() ns.logger.Debug("deactivating namespace", slog.String("id", namespaceID)) rsp := &namespaces.DeactivateNamespaceResponse{} @@ -173,11 +173,13 @@ func (ns NamespacesService) DeactivateNamespace(ctx context.Context, req *namesp ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) ns.logger.Debug("soft-deleted namespace", slog.String("id", namespaceID)) - return rsp, nil + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) AssignKeyAccessServerToNamespace(ctx context.Context, req *namespaces.AssignKeyAccessServerToNamespaceRequest) (*namespaces.AssignKeyAccessServerToNamespaceResponse, error) { - grant := req.GetNamespaceKeyAccessServer() +func (ns NamespacesService) AssignKeyAccessServerToNamespace(ctx context.Context, req *connect.Request[namespaces.AssignKeyAccessServerToNamespaceRequest]) (*connect.Response[namespaces.AssignKeyAccessServerToNamespaceResponse], error) { + rsp := &namespaces.AssignKeyAccessServerToNamespaceResponse{} + + grant := req.Msg.GetNamespaceKeyAccessServer() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeKasAttributeNamespaceAssignment, @@ -191,13 +193,15 @@ func (ns NamespacesService) AssignKeyAccessServerToNamespace(ctx context.Context } ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &namespaces.AssignKeyAccessServerToNamespaceResponse{ - NamespaceKeyAccessServer: namespaceKas, - }, nil + rsp.NamespaceKeyAccessServer = namespaceKas + + return connect.NewResponse(rsp), nil } -func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Context, req *namespaces.RemoveKeyAccessServerFromNamespaceRequest) (*namespaces.RemoveKeyAccessServerFromNamespaceResponse, error) { - grant := req.GetNamespaceKeyAccessServer() +func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Context, req *connect.Request[namespaces.RemoveKeyAccessServerFromNamespaceRequest]) (*connect.Response[namespaces.RemoveKeyAccessServerFromNamespaceResponse], error) { + rsp := &namespaces.RemoveKeyAccessServerFromNamespaceResponse{} + + grant := req.Msg.GetNamespaceKeyAccessServer() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeKasAttributeNamespaceAssignment, @@ -211,7 +215,7 @@ func (ns NamespacesService) RemoveKeyAccessServerFromNamespace(ctx context.Conte } ns.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &namespaces.RemoveKeyAccessServerFromNamespaceResponse{ - NamespaceKeyAccessServer: namespaceKas, - }, nil + rsp.NamespaceKeyAccessServer = namespaceKas + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/namespaces/namespaces.proto b/service/policy/namespaces/namespaces.proto index 984824e5e1..bb1e3730e2 100644 --- a/service/policy/namespaces/namespaces.proto +++ b/service/policy/namespaces/namespaces.proto @@ -119,10 +119,12 @@ message RemoveKeyAccessServerFromNamespaceResponse { service NamespaceService { rpc GetNamespace(GetNamespaceRequest) returns (GetNamespaceResponse) { option (google.api.http) = {get: "/attributes/namespaces/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc ListNamespaces(ListNamespacesRequest) returns (ListNamespacesResponse) { option (google.api.http) = {get: "/attributes/namespaces"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateNamespace(CreateNamespaceRequest) returns (CreateNamespaceResponse) { diff --git a/service/policy/resourcemapping/resource_mapping.go b/service/policy/resourcemapping/resource_mapping.go index 54e732172e..ba41489ce0 100644 --- a/service/policy/resourcemapping/resource_mapping.go +++ b/service/policy/resourcemapping/resource_mapping.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/resourcemapping" + "github.com/opentdf/platform/protocol/go/policy/resourcemapping/resourcemappingconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,22 +16,21 @@ import ( ) type ResourceMappingService struct { //nolint:revive // ResourceMappingService is a valid name for this struct - resourcemapping.UnimplementedResourceMappingServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[ResourceMappingService] { - return &serviceregistry.Service[ResourceMappingService]{ - ServiceOptions: serviceregistry.ServiceOptions[ResourceMappingService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &resourcemapping.ResourceMappingService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*ResourceMappingService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[resourcemappingconnect.ResourceMappingServiceHandler] { + return &serviceregistry.Service[resourcemappingconnect.ResourceMappingServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[resourcemappingconnect.ResourceMappingServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &resourcemapping.ResourceMappingService_ServiceDesc, + ConnectRPCFunc: resourcemappingconnect.NewResourceMappingServiceHandler, + GRPCGateayFunc: resourcemapping.RegisterResourceMappingServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (resourcemappingconnect.ResourceMappingServiceHandler, serviceregistry.HandlerServer) { rm := &ResourceMappingService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return rm, func(ctx context.Context, mux *runtime.ServeMux) error { - return resourcemapping.RegisterResourceMappingServiceHandlerServer(ctx, mux, rm) - } + return rm, nil }, }, } @@ -40,51 +40,59 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer Resource Mapping Groups */ -func (s ResourceMappingService) ListResourceMappingGroups(ctx context.Context, req *resourcemapping.ListResourceMappingGroupsRequest) (*resourcemapping.ListResourceMappingGroupsResponse, error) { - rmGroups, err := s.dbClient.ListResourceMappingGroups(ctx, req) +func (s ResourceMappingService) ListResourceMappingGroups(ctx context.Context, req *connect.Request[resourcemapping.ListResourceMappingGroupsRequest]) (*connect.Response[resourcemapping.ListResourceMappingGroupsResponse], error) { + rsp := &resourcemapping.ListResourceMappingGroupsResponse{} + + rmGroups, err := s.dbClient.ListResourceMappingGroups(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &resourcemapping.ListResourceMappingGroupsResponse{ - ResourceMappingGroups: rmGroups, - }, nil + rsp.ResourceMappingGroups = rmGroups + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) GetResourceMappingGroup(ctx context.Context, req *resourcemapping.GetResourceMappingGroupRequest) (*resourcemapping.GetResourceMappingGroupResponse, error) { - rmGroup, err := s.dbClient.GetResourceMappingGroup(ctx, req.GetId()) +func (s ResourceMappingService) GetResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.GetResourceMappingGroupRequest]) (*connect.Response[resourcemapping.GetResourceMappingGroupResponse], error) { + rsp := &resourcemapping.GetResourceMappingGroupResponse{} + + rmGroup, err := s.dbClient.GetResourceMappingGroup(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &resourcemapping.GetResourceMappingGroupResponse{ - ResourceMappingGroup: rmGroup, - }, nil + rsp.ResourceMappingGroup = rmGroup + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) CreateResourceMappingGroup(ctx context.Context, req *resourcemapping.CreateResourceMappingGroupRequest) (*resourcemapping.CreateResourceMappingGroupResponse, error) { +func (s ResourceMappingService) CreateResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.CreateResourceMappingGroupRequest]) (*connect.Response[resourcemapping.CreateResourceMappingGroupResponse], error) { + rsp := &resourcemapping.CreateResourceMappingGroupResponse{} + auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeResourceMappingGroup, } - rmGroup, err := s.dbClient.CreateResourceMappingGroup(ctx, req) + rmGroup, err := s.dbClient.CreateResourceMappingGroup(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMappingGroup", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMappingGroup", req.Msg.String())) } auditParams.ObjectID = rmGroup.GetId() auditParams.Original = rmGroup s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.CreateResourceMappingGroupResponse{ - ResourceMappingGroup: rmGroup, - }, nil + rsp.ResourceMappingGroup = rmGroup + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, req *resourcemapping.UpdateResourceMappingGroupRequest) (*resourcemapping.UpdateResourceMappingGroupResponse, error) { - id := req.GetId() +func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.UpdateResourceMappingGroupRequest]) (*connect.Response[resourcemapping.UpdateResourceMappingGroupResponse], error) { + rsp := &resourcemapping.UpdateResourceMappingGroupResponse{} + + id := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -98,7 +106,7 @@ func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - updatedRmGroup, err := s.dbClient.UpdateResourceMappingGroup(ctx, id, req) + updatedRmGroup, err := s.dbClient.UpdateResourceMappingGroup(ctx, id, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id)) @@ -109,15 +117,17 @@ func (s ResourceMappingService) UpdateResourceMappingGroup(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.UpdateResourceMappingGroupResponse{ - ResourceMappingGroup: &policy.ResourceMappingGroup{ - Id: id, - }, - }, nil + rsp.ResourceMappingGroup = &policy.ResourceMappingGroup{ + Id: id, + } + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, req *resourcemapping.DeleteResourceMappingGroupRequest) (*resourcemapping.DeleteResourceMappingGroupResponse, error) { - id := req.GetId() +func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, req *connect.Request[resourcemapping.DeleteResourceMappingGroupRequest]) (*connect.Response[resourcemapping.DeleteResourceMappingGroupResponse], error) { + rsp := &resourcemapping.DeleteResourceMappingGroupResponse{} + + id := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, @@ -133,11 +143,11 @@ func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.DeleteResourceMappingGroupResponse{ - ResourceMappingGroup: &policy.ResourceMappingGroup{ - Id: id, - }, - }, nil + rsp.ResourceMappingGroup = &policy.ResourceMappingGroup{ + Id: id, + } + + return connect.NewResponse(rsp), nil } /* @@ -145,47 +155,55 @@ func (s ResourceMappingService) DeleteResourceMappingGroup(ctx context.Context, */ func (s ResourceMappingService) ListResourceMappings(ctx context.Context, - req *resourcemapping.ListResourceMappingsRequest, -) (*resourcemapping.ListResourceMappingsResponse, error) { - resourceMappings, err := s.dbClient.ListResourceMappings(ctx, req) + req *connect.Request[resourcemapping.ListResourceMappingsRequest], +) (*connect.Response[resourcemapping.ListResourceMappingsResponse], error) { + rsp := &resourcemapping.ListResourceMappingsResponse{} + + resourceMappings, err := s.dbClient.ListResourceMappings(ctx, req.Msg) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - return &resourcemapping.ListResourceMappingsResponse{ - ResourceMappings: resourceMappings, - }, nil + rsp.ResourceMappings = resourceMappings + + return connect.NewResponse(rsp), nil } -func (s ResourceMappingService) ListResourceMappingsByGroupFqns(ctx context.Context, req *resourcemapping.ListResourceMappingsByGroupFqnsRequest) (*resourcemapping.ListResourceMappingsByGroupFqnsResponse, error) { - fqns := req.GetFqns() +func (s ResourceMappingService) ListResourceMappingsByGroupFqns(ctx context.Context, req *connect.Request[resourcemapping.ListResourceMappingsByGroupFqnsRequest]) (*connect.Response[resourcemapping.ListResourceMappingsByGroupFqnsResponse], error) { + rsp := &resourcemapping.ListResourceMappingsByGroupFqnsResponse{} + + fqns := req.Msg.GetFqns() fqnRmGroupMap, err := s.dbClient.ListResourceMappingsByGroupFqns(ctx, fqns) if err != nil { return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed, slog.Any("fqns", fqns)) } - return &resourcemapping.ListResourceMappingsByGroupFqnsResponse{ - FqnResourceMappingGroups: fqnRmGroupMap, - }, nil + rsp.FqnResourceMappingGroups = fqnRmGroupMap + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) GetResourceMapping(ctx context.Context, - req *resourcemapping.GetResourceMappingRequest, -) (*resourcemapping.GetResourceMappingResponse, error) { - rm, err := s.dbClient.GetResourceMapping(ctx, req.GetId()) + req *connect.Request[resourcemapping.GetResourceMappingRequest], +) (*connect.Response[resourcemapping.GetResourceMappingResponse], error) { + rsp := &resourcemapping.GetResourceMappingResponse{} + + rm, err := s.dbClient.GetResourceMapping(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } - return &resourcemapping.GetResourceMappingResponse{ - ResourceMapping: rm, - }, nil + rsp.ResourceMapping = rm + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) CreateResourceMapping(ctx context.Context, - req *resourcemapping.CreateResourceMappingRequest, -) (*resourcemapping.CreateResourceMappingResponse, error) { + req *connect.Request[resourcemapping.CreateResourceMappingRequest], +) (*connect.Response[resourcemapping.CreateResourceMappingResponse], error) { + rsp := &resourcemapping.CreateResourceMappingResponse{} + s.logger.Debug("creating resource mapping") auditParams := audit.PolicyEventParams{ @@ -193,25 +211,27 @@ func (s ResourceMappingService) CreateResourceMapping(ctx context.Context, ObjectType: audit.ObjectTypeResourceMapping, } - rm, err := s.dbClient.CreateResourceMapping(ctx, req) + rm, err := s.dbClient.CreateResourceMapping(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMapping", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("resourceMapping", req.Msg.String())) } auditParams.ObjectID = rm.GetId() auditParams.Original = rm s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.CreateResourceMappingResponse{ - ResourceMapping: rm, - }, nil + rsp.ResourceMapping = rm + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) UpdateResourceMapping(ctx context.Context, - req *resourcemapping.UpdateResourceMappingRequest, -) (*resourcemapping.UpdateResourceMappingResponse, error) { - resourceMappingID := req.GetId() + req *connect.Request[resourcemapping.UpdateResourceMappingRequest], +) (*connect.Response[resourcemapping.UpdateResourceMappingResponse], error) { + rsp := &resourcemapping.UpdateResourceMappingResponse{} + + resourceMappingID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -225,12 +245,12 @@ func (s ResourceMappingService) UpdateResourceMapping(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextListRetrievalFailed) } - updatedRM, err := s.dbClient.UpdateResourceMapping(ctx, resourceMappingID, req) + updatedRM, err := s.dbClient.UpdateResourceMapping(ctx, resourceMappingID, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, - slog.String("id", req.GetId()), - slog.String("resourceMapping", req.String()), + slog.String("id", req.Msg.GetId()), + slog.String("resourceMapping", req.Msg.String()), ) } @@ -238,17 +258,19 @@ func (s ResourceMappingService) UpdateResourceMapping(ctx context.Context, auditParams.Updated = updatedRM s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.UpdateResourceMappingResponse{ - ResourceMapping: &policy.ResourceMapping{ - Id: resourceMappingID, - }, - }, nil + rsp.ResourceMapping = &policy.ResourceMapping{ + Id: resourceMappingID, + } + + return connect.NewResponse(rsp), nil } func (s ResourceMappingService) DeleteResourceMapping(ctx context.Context, - req *resourcemapping.DeleteResourceMappingRequest, -) (*resourcemapping.DeleteResourceMappingResponse, error) { - resourceMappingID := req.GetId() + req *connect.Request[resourcemapping.DeleteResourceMappingRequest], +) (*connect.Response[resourcemapping.DeleteResourceMappingResponse], error) { + rsp := &resourcemapping.DeleteResourceMappingResponse{} + + resourceMappingID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, @@ -264,9 +286,9 @@ func (s ResourceMappingService) DeleteResourceMapping(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - return &resourcemapping.DeleteResourceMappingResponse{ - ResourceMapping: &policy.ResourceMapping{ - Id: resourceMappingID, - }, - }, nil + rsp.ResourceMapping = &policy.ResourceMapping{ + Id: resourceMappingID, + } + + return connect.NewResponse(rsp), nil } diff --git a/service/policy/resourcemapping/resource_mapping.proto b/service/policy/resourcemapping/resource_mapping.proto index cd95243513..e925fe441c 100644 --- a/service/policy/resourcemapping/resource_mapping.proto +++ b/service/policy/resourcemapping/resource_mapping.proto @@ -241,10 +241,12 @@ service ResourceMappingService { rpc ListResourceMappingGroups(ListResourceMappingGroupsRequest) returns (ListResourceMappingGroupsResponse) { option (google.api.http) = {get: "/resource-mapping-groups"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetResourceMappingGroup(GetResourceMappingGroupRequest) returns (GetResourceMappingGroupResponse) { option (google.api.http) = {get: "/resource-mapping-groups/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateResourceMappingGroup(CreateResourceMappingGroupRequest) returns (CreateResourceMappingGroupResponse) { @@ -271,14 +273,17 @@ service ResourceMappingService { rpc ListResourceMappings(ListResourceMappingsRequest) returns (ListResourceMappingsResponse) { option (google.api.http) = {get: "/resource-mappings"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc ListResourceMappingsByGroupFqns(ListResourceMappingsByGroupFqnsRequest) returns (ListResourceMappingsByGroupFqnsResponse) { option (google.api.http) = {get: "/resource-mappings/group-fqns"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetResourceMapping(GetResourceMappingRequest) returns (GetResourceMappingResponse) { option (google.api.http) = {get: "/resource-mappings/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateResourceMapping(CreateResourceMappingRequest) returns (CreateResourceMappingResponse) { diff --git a/service/policy/subjectmapping/subject_mapping.go b/service/policy/subjectmapping/subject_mapping.go index 31197fa2de..d089fe2904 100644 --- a/service/policy/subjectmapping/subject_mapping.go +++ b/service/policy/subjectmapping/subject_mapping.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" sm "github.com/opentdf/platform/protocol/go/policy/subjectmapping" + "github.com/opentdf/platform/protocol/go/policy/subjectmapping/subjectmappingconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,22 +16,21 @@ import ( ) type SubjectMappingService struct { //nolint:revive // SubjectMappingService is a valid name for this struct - sm.UnimplementedSubjectMappingServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[SubjectMappingService] { - return &serviceregistry.Service[SubjectMappingService]{ - ServiceOptions: serviceregistry.ServiceOptions[SubjectMappingService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &sm.SubjectMappingService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*SubjectMappingService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[subjectmappingconnect.SubjectMappingServiceHandler] { + return &serviceregistry.Service[subjectmappingconnect.SubjectMappingServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[subjectmappingconnect.SubjectMappingServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &sm.SubjectMappingService_ServiceDesc, + ConnectRPCFunc: subjectmappingconnect.NewSubjectMappingServiceHandler, + GRPCGateayFunc: sm.RegisterSubjectMappingServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (subjectmappingconnect.SubjectMappingServiceHandler, serviceregistry.HandlerServer) { smSvc := &SubjectMappingService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return smSvc, func(ctx context.Context, mux *runtime.ServeMux) error { - return sm.RegisterSubjectMappingServiceHandlerServer(ctx, mux, smSvc) - } + return smSvc, nil }, }, } @@ -41,8 +41,8 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer * --------------------------------------------------*/ func (s SubjectMappingService) CreateSubjectMapping(ctx context.Context, - req *sm.CreateSubjectMappingRequest, -) (*sm.CreateSubjectMappingResponse, error) { + req *connect.Request[sm.CreateSubjectMappingRequest], +) (*connect.Response[sm.CreateSubjectMappingResponse], error) { rsp := &sm.CreateSubjectMappingResponse{} s.logger.Debug("creating subject mapping") @@ -51,23 +51,23 @@ func (s SubjectMappingService) CreateSubjectMapping(ctx context.Context, ObjectType: audit.ObjectTypeSubjectMapping, } - sm, err := s.dbClient.CreateSubjectMapping(ctx, req) + subjectMapping, err := s.dbClient.CreateSubjectMapping(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectMapping", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectMapping", req.Msg.String())) } - auditParams.ObjectID = sm.GetId() - auditParams.Original = sm + auditParams.ObjectID = subjectMapping.GetId() + auditParams.Original = subjectMapping s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) - rsp.SubjectMapping = sm - return rsp, nil + rsp.SubjectMapping = subjectMapping + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) ListSubjectMappings(ctx context.Context, - _ *sm.ListSubjectMappingsRequest, -) (*sm.ListSubjectMappingsResponse, error) { + _ *connect.Request[sm.ListSubjectMappingsRequest], +) (*connect.Response[sm.ListSubjectMappingsResponse], error) { rsp := &sm.ListSubjectMappingsResponse{} s.logger.Debug("listing subject mappings") @@ -77,31 +77,31 @@ func (s SubjectMappingService) ListSubjectMappings(ctx context.Context, } rsp.SubjectMappings = mappings - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) GetSubjectMapping(ctx context.Context, - req *sm.GetSubjectMappingRequest, -) (*sm.GetSubjectMappingResponse, error) { + req *connect.Request[sm.GetSubjectMappingRequest], +) (*connect.Response[sm.GetSubjectMappingResponse], error) { rsp := &sm.GetSubjectMappingResponse{} - s.logger.Debug("getting subject mapping", slog.String("id", req.GetId())) + s.logger.Debug("getting subject mapping", slog.String("id", req.Msg.GetId())) - mapping, err := s.dbClient.GetSubjectMapping(ctx, req.GetId()) + mapping, err := s.dbClient.GetSubjectMapping(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } rsp.SubjectMapping = mapping - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) UpdateSubjectMapping(ctx context.Context, - req *sm.UpdateSubjectMappingRequest, -) (*sm.UpdateSubjectMappingResponse, error) { + req *connect.Request[sm.UpdateSubjectMappingRequest], +) (*connect.Response[sm.UpdateSubjectMappingResponse], error) { rsp := &sm.UpdateSubjectMappingResponse{} - subjectMappingID := req.GetId() + subjectMappingID := req.Msg.GetId() - s.logger.Debug("updating subject mapping", slog.String("subjectMapping", req.String())) + s.logger.Debug("updating subject mapping", slog.String("subjectMapping", req.Msg.String())) auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, @@ -115,10 +115,10 @@ func (s SubjectMappingService) UpdateSubjectMapping(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", subjectMappingID)) } - updated, err := s.dbClient.UpdateSubjectMapping(ctx, req) + updated, err := s.dbClient.UpdateSubjectMapping(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("subjectMapping fields", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("subjectMapping fields", req.Msg.String())) } auditParams.Original = original @@ -128,16 +128,16 @@ func (s SubjectMappingService) UpdateSubjectMapping(ctx context.Context, rsp.SubjectMapping = &policy.SubjectMapping{ Id: subjectMappingID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) DeleteSubjectMapping(ctx context.Context, - req *sm.DeleteSubjectMappingRequest, -) (*sm.DeleteSubjectMappingResponse, error) { + req *connect.Request[sm.DeleteSubjectMappingRequest], +) (*connect.Response[sm.DeleteSubjectMappingResponse], error) { rsp := &sm.DeleteSubjectMappingResponse{} - s.logger.Debug("deleting subject mapping", slog.String("id", req.GetId())) + s.logger.Debug("deleting subject mapping", slog.String("id", req.Msg.GetId())) - subjectMappingID := req.GetId() + subjectMappingID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeSubjectMapping, @@ -155,22 +155,22 @@ func (s SubjectMappingService) DeleteSubjectMapping(ctx context.Context, rsp.SubjectMapping = &policy.SubjectMapping{ Id: subjectMappingID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) MatchSubjectMappings(ctx context.Context, - req *sm.MatchSubjectMappingsRequest, -) (*sm.MatchSubjectMappingsResponse, error) { + req *connect.Request[sm.MatchSubjectMappingsRequest], +) (*connect.Response[sm.MatchSubjectMappingsResponse], error) { rsp := &sm.MatchSubjectMappingsResponse{} - s.logger.Debug("matching subject mappings", slog.Any("subjectProperties", req.GetSubjectProperties())) + s.logger.Debug("matching subject mappings", slog.Any("subjectProperties", req.Msg.GetSubjectProperties())) - smList, err := s.dbClient.GetMatchedSubjectMappings(ctx, req.GetSubjectProperties()) + smList, err := s.dbClient.GetMatchedSubjectMappings(ctx, req.Msg.GetSubjectProperties()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.Any("subjectProperties", req.GetSubjectProperties())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.Any("subjectProperties", req.Msg.GetSubjectProperties())) } rsp.SubjectMappings = smList - return rsp, nil + return connect.NewResponse(rsp), nil } /* -------------------------------------------------------- @@ -178,23 +178,23 @@ func (s SubjectMappingService) MatchSubjectMappings(ctx context.Context, * -------------------------------------------------------*/ func (s SubjectMappingService) GetSubjectConditionSet(ctx context.Context, - req *sm.GetSubjectConditionSetRequest, -) (*sm.GetSubjectConditionSetResponse, error) { + req *connect.Request[sm.GetSubjectConditionSetRequest], +) (*connect.Response[sm.GetSubjectConditionSetResponse], error) { rsp := &sm.GetSubjectConditionSetResponse{} - s.logger.Debug("getting subject condition set", slog.String("id", req.GetId())) + s.logger.Debug("getting subject condition set", slog.String("id", req.Msg.GetId())) - conditionSet, err := s.dbClient.GetSubjectConditionSet(ctx, req.GetId()) + conditionSet, err := s.dbClient.GetSubjectConditionSet(ctx, req.Msg.GetId()) if err != nil { - return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.GetId())) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", req.Msg.GetId())) } rsp.SubjectConditionSet = conditionSet - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) ListSubjectConditionSets(ctx context.Context, - _ *sm.ListSubjectConditionSetsRequest, -) (*sm.ListSubjectConditionSetsResponse, error) { + _ *connect.Request[sm.ListSubjectConditionSetsRequest], +) (*connect.Response[sm.ListSubjectConditionSetsResponse], error) { rsp := &sm.ListSubjectConditionSetsResponse{} s.logger.Debug("listing subject condition sets") @@ -204,24 +204,24 @@ func (s SubjectMappingService) ListSubjectConditionSets(ctx context.Context, } rsp.SubjectConditionSets = conditionSets - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) CreateSubjectConditionSet(ctx context.Context, - req *sm.CreateSubjectConditionSetRequest, -) (*sm.CreateSubjectConditionSetResponse, error) { + req *connect.Request[sm.CreateSubjectConditionSetRequest], +) (*connect.Response[sm.CreateSubjectConditionSetResponse], error) { rsp := &sm.CreateSubjectConditionSetResponse{} - s.logger.Debug("creating subject condition set", slog.String("subjectConditionSet", req.String())) + s.logger.Debug("creating subject condition set", slog.String("subjectConditionSet", req.Msg.String())) auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeCreate, ObjectType: audit.ObjectTypeConditionSet, } - conditionSet, err := s.dbClient.CreateSubjectConditionSet(ctx, req.GetSubjectConditionSet()) + conditionSet, err := s.dbClient.CreateSubjectConditionSet(ctx, req.Msg.GetSubjectConditionSet()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectConditionSet", req.String())) + return nil, db.StatusifyError(err, db.ErrTextCreationFailed, slog.String("subjectConditionSet", req.Msg.String())) } auditParams.ObjectID = conditionSet.GetId() @@ -229,16 +229,16 @@ func (s SubjectMappingService) CreateSubjectConditionSet(ctx context.Context, s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) rsp.SubjectConditionSet = conditionSet - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) UpdateSubjectConditionSet(ctx context.Context, - req *sm.UpdateSubjectConditionSetRequest, -) (*sm.UpdateSubjectConditionSetResponse, error) { + req *connect.Request[sm.UpdateSubjectConditionSetRequest], +) (*connect.Response[sm.UpdateSubjectConditionSetResponse], error) { rsp := &sm.UpdateSubjectConditionSetResponse{} - s.logger.Debug("updating subject condition set", slog.String("subjectConditionSet", req.String())) + s.logger.Debug("updating subject condition set", slog.String("subjectConditionSet", req.Msg.String())) - subjectConditionSetID := req.GetId() + subjectConditionSetID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeUpdate, ObjectType: audit.ObjectTypeConditionSet, @@ -251,10 +251,10 @@ func (s SubjectMappingService) UpdateSubjectConditionSet(ctx context.Context, return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", subjectConditionSetID)) } - updated, err := s.dbClient.UpdateSubjectConditionSet(ctx, req) + updated, err := s.dbClient.UpdateSubjectConditionSet(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.GetId()), slog.String("subjectConditionSet fields", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", req.Msg.GetId()), slog.String("subjectConditionSet fields", req.Msg.String())) } auditParams.Original = original @@ -264,16 +264,16 @@ func (s SubjectMappingService) UpdateSubjectConditionSet(ctx context.Context, rsp.SubjectConditionSet = &policy.SubjectConditionSet{ Id: subjectConditionSetID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) DeleteSubjectConditionSet(ctx context.Context, - req *sm.DeleteSubjectConditionSetRequest, -) (*sm.DeleteSubjectConditionSetResponse, error) { + req *connect.Request[sm.DeleteSubjectConditionSetRequest], +) (*connect.Response[sm.DeleteSubjectConditionSetResponse], error) { rsp := &sm.DeleteSubjectConditionSetResponse{} - s.logger.Debug("deleting subject condition set", slog.String("id", req.GetId())) + s.logger.Debug("deleting subject condition set", slog.String("id", req.Msg.GetId())) - conditionSetID := req.GetId() + conditionSetID := req.Msg.GetId() auditParams := audit.PolicyEventParams{ ActionType: audit.ActionTypeDelete, ObjectType: audit.ObjectTypeConditionSet, @@ -291,12 +291,12 @@ func (s SubjectMappingService) DeleteSubjectConditionSet(ctx context.Context, rsp.SubjectConditionSet = &policy.SubjectConditionSet{ Id: conditionSetID, } - return rsp, nil + return connect.NewResponse(rsp), nil } func (s SubjectMappingService) DeleteAllUnmappedSubjectConditionSets(ctx context.Context, - _ *sm.DeleteAllUnmappedSubjectConditionSetsRequest, -) (*sm.DeleteAllUnmappedSubjectConditionSetsResponse, error) { + _ *connect.Request[sm.DeleteAllUnmappedSubjectConditionSetsRequest], +) (*connect.Response[sm.DeleteAllUnmappedSubjectConditionSetsResponse], error) { rsp := &sm.DeleteAllUnmappedSubjectConditionSetsResponse{} s.logger.Debug("deleting all unmapped subject condition sets") @@ -318,5 +318,5 @@ func (s SubjectMappingService) DeleteAllUnmappedSubjectConditionSets(ctx context } rsp.SubjectConditionSets = deleted - return rsp, nil + return connect.NewResponse(rsp), nil } diff --git a/service/policy/subjectmapping/subject_mapping.proto b/service/policy/subjectmapping/subject_mapping.proto index 6eb7521a73..b858e3287e 100644 --- a/service/policy/subjectmapping/subject_mapping.proto +++ b/service/policy/subjectmapping/subject_mapping.proto @@ -197,9 +197,11 @@ service SubjectMappingService { rpc ListSubjectMappings(ListSubjectMappingsRequest) returns (ListSubjectMappingsResponse) { option (google.api.http) = {get: "/subject-mappings"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetSubjectMapping(GetSubjectMappingRequest) returns (GetSubjectMappingResponse) { option (google.api.http) = {get: "/subject-mappings/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateSubjectMapping(CreateSubjectMappingRequest) returns (CreateSubjectMappingResponse) { @@ -222,10 +224,12 @@ service SubjectMappingService { rpc ListSubjectConditionSets(ListSubjectConditionSetsRequest) returns (ListSubjectConditionSetsResponse) { option (google.api.http) = {get: "/subject-condition-sets"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc GetSubjectConditionSet(GetSubjectConditionSetRequest) returns (GetSubjectConditionSetResponse) { option (google.api.http) = {get: "/subject-condition-sets/{id}"}; + option idempotency_level = NO_SIDE_EFFECTS; } rpc CreateSubjectConditionSet(CreateSubjectConditionSetRequest) returns (CreateSubjectConditionSetResponse) { diff --git a/service/policy/unsafe/unsafe.go b/service/policy/unsafe/unsafe.go index ed1f2700ec..065866b0be 100644 --- a/service/policy/unsafe/unsafe.go +++ b/service/policy/unsafe/unsafe.go @@ -4,9 +4,10 @@ import ( "context" "log/slog" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/unsafe" + "github.com/opentdf/platform/protocol/go/policy/unsafe/unsafeconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" "github.com/opentdf/platform/service/pkg/db" @@ -15,22 +16,20 @@ import ( ) type UnsafeService struct { //nolint:revive // UnsafeService is a valid name for this struct - unsafe.UnimplementedUnsafeServiceServer dbClient policydb.PolicyDBClient logger *logger.Logger } -func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[UnsafeService] { - return &serviceregistry.Service[UnsafeService]{ - ServiceOptions: serviceregistry.ServiceOptions[UnsafeService]{ - Namespace: ns, - DB: dbRegister, - ServiceDesc: &unsafe.UnsafeService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*UnsafeService, serviceregistry.HandlerServer) { +func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *serviceregistry.Service[unsafeconnect.UnsafeServiceHandler] { + return &serviceregistry.Service[unsafeconnect.UnsafeServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[unsafeconnect.UnsafeServiceHandler]{ + Namespace: ns, + DB: dbRegister, + ServiceDesc: &unsafe.UnsafeService_ServiceDesc, + ConnectRPCFunc: unsafeconnect.NewUnsafeServiceHandler, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (unsafeconnect.UnsafeServiceHandler, serviceregistry.HandlerServer) { unsafeSvc := &UnsafeService{dbClient: policydb.NewClient(srp.DBClient, srp.Logger), logger: srp.Logger} - return unsafeSvc, func(ctx context.Context, mux *runtime.ServeMux) error { - return unsafe.RegisterUnsafeServiceHandlerServer(ctx, mux, unsafeSvc) - } + return unsafeSvc, nil }, }, } @@ -40,9 +39,9 @@ func NewRegistration(ns string, dbRegister serviceregistry.DBRegister) *servicer // Unsafe Namespace RPCs // -func (s *UnsafeService) UnsafeUpdateNamespace(ctx context.Context, req *unsafe.UnsafeUpdateNamespaceRequest) (*unsafe.UnsafeUpdateNamespaceResponse, error) { - id := req.GetId() - name := req.GetName() +func (s *UnsafeService) UnsafeUpdateNamespace(ctx context.Context, req *connect.Request[unsafe.UnsafeUpdateNamespaceRequest]) (*connect.Response[unsafe.UnsafeUpdateNamespaceResponse], error) { + id := req.Msg.GetId() + name := req.Msg.GetName() rsp := &unsafe.UnsafeUpdateNamespaceResponse{} @@ -73,11 +72,11 @@ func (s *UnsafeService) UnsafeUpdateNamespace(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeReactivateNamespace(ctx context.Context, req *unsafe.UnsafeReactivateNamespaceRequest) (*unsafe.UnsafeReactivateNamespaceResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeReactivateNamespace(ctx context.Context, req *connect.Request[unsafe.UnsafeReactivateNamespaceRequest]) (*connect.Response[unsafe.UnsafeReactivateNamespaceResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeReactivateNamespaceResponse{} @@ -108,11 +107,11 @@ func (s *UnsafeService) UnsafeReactivateNamespace(ctx context.Context, req *unsa Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *unsafe.UnsafeDeleteNamespaceRequest) (*unsafe.UnsafeDeleteNamespaceResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *connect.Request[unsafe.UnsafeDeleteNamespaceRequest]) (*connect.Response[unsafe.UnsafeDeleteNamespaceResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeDeleteNamespaceResponse{} @@ -128,7 +127,7 @@ func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *unsafe.U return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - _, err = s.dbClient.UnsafeDeleteNamespace(ctx, existing, req.GetFqn()) + _, err = s.dbClient.UnsafeDeleteNamespace(ctx, existing, req.Msg.GetFqn()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", id)) @@ -140,15 +139,15 @@ func (s *UnsafeService) UnsafeDeleteNamespace(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } // // Unsafe Attribute Definition RPCs // -func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *unsafe.UnsafeUpdateAttributeRequest) (*unsafe.UnsafeUpdateAttributeResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *connect.Request[unsafe.UnsafeUpdateAttributeRequest]) (*connect.Response[unsafe.UnsafeUpdateAttributeResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeUpdateAttributeResponse{} @@ -164,10 +163,10 @@ func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *unsafe.U return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - updated, err := s.dbClient.UnsafeUpdateAttribute(ctx, req) + updated, err := s.dbClient.UnsafeUpdateAttribute(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute", req.Msg.String())) } auditParams.Original = original @@ -179,11 +178,11 @@ func (s *UnsafeService) UnsafeUpdateAttribute(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeReactivateAttribute(ctx context.Context, req *unsafe.UnsafeReactivateAttributeRequest) (*unsafe.UnsafeReactivateAttributeResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeReactivateAttribute(ctx context.Context, req *connect.Request[unsafe.UnsafeReactivateAttributeRequest]) (*connect.Response[unsafe.UnsafeReactivateAttributeResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeReactivateAttributeResponse{} @@ -214,11 +213,11 @@ func (s *UnsafeService) UnsafeReactivateAttribute(ctx context.Context, req *unsa Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *unsafe.UnsafeDeleteAttributeRequest) (*unsafe.UnsafeDeleteAttributeResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *connect.Request[unsafe.UnsafeDeleteAttributeRequest]) (*connect.Response[unsafe.UnsafeDeleteAttributeResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeDeleteAttributeResponse{} @@ -234,7 +233,7 @@ func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *unsafe.U return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - _, err = s.dbClient.UnsafeDeleteAttribute(ctx, existing, req.GetFqn()) + _, err = s.dbClient.UnsafeDeleteAttribute(ctx, existing, req.Msg.GetFqn()) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", id)) @@ -246,15 +245,15 @@ func (s *UnsafeService) UnsafeDeleteAttribute(ctx context.Context, req *unsafe.U Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } // // Unsafe Attribute Value RPCs // -func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *unsafe.UnsafeUpdateAttributeValueRequest) (*unsafe.UnsafeUpdateAttributeValueResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *connect.Request[unsafe.UnsafeUpdateAttributeValueRequest]) (*connect.Response[unsafe.UnsafeUpdateAttributeValueResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeUpdateAttributeValueResponse{} @@ -270,10 +269,10 @@ func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *uns return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - updated, err := s.dbClient.UnsafeUpdateAttributeValue(ctx, req) + updated, err := s.dbClient.UnsafeUpdateAttributeValue(ctx, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) - return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute_value", req.String())) + return nil, db.StatusifyError(err, db.ErrTextUpdateFailed, slog.String("id", id), slog.String("attribute_value", req.Msg.String())) } auditParams.Original = original @@ -284,11 +283,11 @@ func (s *UnsafeService) UnsafeUpdateAttributeValue(ctx context.Context, req *uns rsp.Value = &policy.Value{ Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeReactivateAttributeValue(ctx context.Context, req *unsafe.UnsafeReactivateAttributeValueRequest) (*unsafe.UnsafeReactivateAttributeValueResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeReactivateAttributeValue(ctx context.Context, req *connect.Request[unsafe.UnsafeReactivateAttributeValueRequest]) (*connect.Response[unsafe.UnsafeReactivateAttributeValueResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeReactivateAttributeValueResponse{} @@ -318,11 +317,11 @@ func (s *UnsafeService) UnsafeReactivateAttributeValue(ctx context.Context, req rsp.Value = &policy.Value{ Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } -func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *unsafe.UnsafeDeleteAttributeValueRequest) (*unsafe.UnsafeDeleteAttributeValueResponse, error) { - id := req.GetId() +func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *connect.Request[unsafe.UnsafeDeleteAttributeValueRequest]) (*connect.Response[unsafe.UnsafeDeleteAttributeValueResponse], error) { + id := req.Msg.GetId() rsp := &unsafe.UnsafeDeleteAttributeValueResponse{} @@ -338,7 +337,7 @@ func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *uns return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("id", id)) } - _, err = s.dbClient.UnsafeDeleteAttributeValue(ctx, existing, req) + _, err = s.dbClient.UnsafeDeleteAttributeValue(ctx, existing, req.Msg) if err != nil { s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) return nil, db.StatusifyError(err, db.ErrTextDeletionFailed, slog.String("id", id)) @@ -349,5 +348,5 @@ func (s *UnsafeService) UnsafeDeleteAttributeValue(ctx context.Context, req *uns rsp.Value = &policy.Value{ Id: id, } - return rsp, nil + return connect.NewResponse(rsp), nil } diff --git a/service/wellknownconfiguration/wellknown_configuration.go b/service/wellknownconfiguration/wellknown_configuration.go index bbfb34e3ad..88a096688a 100644 --- a/service/wellknownconfiguration/wellknown_configuration.go +++ b/service/wellknownconfiguration/wellknown_configuration.go @@ -6,8 +6,9 @@ import ( "log/slog" "sync" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "connectrpc.com/connect" wellknown "github.com/opentdf/platform/protocol/go/wellknownconfiguration" + "github.com/opentdf/platform/protocol/go/wellknownconfiguration/wellknownconfigurationconnect" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" @@ -16,7 +17,6 @@ import ( ) type WellKnownService struct { - wellknown.UnimplementedWellKnownServiceServer logger *logger.Logger } @@ -35,22 +35,22 @@ func RegisterConfiguration(namespace string, config any) error { return nil } -func NewRegistration() *serviceregistry.Service[WellKnownService] { - return &serviceregistry.Service[WellKnownService]{ - ServiceOptions: serviceregistry.ServiceOptions[WellKnownService]{ - Namespace: "wellknown", - ServiceDesc: &wellknown.WellKnownService_ServiceDesc, - RegisterFunc: func(srp serviceregistry.RegistrationParams) (*WellKnownService, serviceregistry.HandlerServer) { +func NewRegistration() *serviceregistry.Service[wellknownconfigurationconnect.WellKnownServiceHandler] { + return &serviceregistry.Service[wellknownconfigurationconnect.WellKnownServiceHandler]{ + ServiceOptions: serviceregistry.ServiceOptions[wellknownconfigurationconnect.WellKnownServiceHandler]{ + Namespace: "wellknown", + ServiceDesc: &wellknown.WellKnownService_ServiceDesc, + ConnectRPCFunc: wellknownconfigurationconnect.NewWellKnownServiceHandler, + GRPCGateayFunc: wellknown.RegisterWellKnownServiceHandlerFromEndpoint, + RegisterFunc: func(srp serviceregistry.RegistrationParams) (wellknownconfigurationconnect.WellKnownServiceHandler, serviceregistry.HandlerServer) { wk := &WellKnownService{logger: srp.Logger} - return wk, func(ctx context.Context, mux *runtime.ServeMux) error { - return wellknown.RegisterWellKnownServiceHandlerServer(ctx, mux, wk) - } + return wk, nil }, }, } } -func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *wellknown.GetWellKnownConfigurationRequest) (*wellknown.GetWellKnownConfigurationResponse, error) { +func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *connect.Request[wellknown.GetWellKnownConfigurationRequest]) (*connect.Response[wellknown.GetWellKnownConfigurationResponse], error) { rwMutex.RLock() cfg, err := structpb.NewStruct(wellKnownConfiguration) rwMutex.RUnlock() @@ -59,7 +59,8 @@ func (s WellKnownService) GetWellKnownConfiguration(_ context.Context, _ *wellkn return nil, status.Error(codes.Internal, "failed to create struct for wellknown configuration") } - return &wellknown.GetWellKnownConfigurationResponse{ + rsp := &wellknown.GetWellKnownConfigurationResponse{ Configuration: cfg, - }, nil + } + return connect.NewResponse(rsp), nil } diff --git a/service/wellknownconfiguration/wellknown_configuration.proto b/service/wellknownconfiguration/wellknown_configuration.proto index 43606adeb7..b6d2c22569 100644 --- a/service/wellknownconfiguration/wellknown_configuration.proto +++ b/service/wellknownconfiguration/wellknown_configuration.proto @@ -18,5 +18,6 @@ message GetWellKnownConfigurationResponse { service WellKnownService { rpc GetWellKnownConfiguration(GetWellKnownConfigurationRequest) returns (GetWellKnownConfigurationResponse) { option (google.api.http) = {get: "/.well-known/opentdf-configuration"}; + option idempotency_level = NO_SIDE_EFFECTS; } }