diff --git a/docs/grpc/index.html b/docs/grpc/index.html index ff3e23131..b9d10acf1 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -446,10 +446,22 @@

Table of Contents

MKAORewrapResult.MetadataEntry +
  • + MKeyAccess +
  • + +
  • + MKeyAccessObjectRequest +
  • +
  • MLegacyPublicKeyRequest
  • +
  • + MPolicyRequest +
  • +
  • MPublicKeyRequest
  • @@ -458,10 +470,18 @@

    Table of Contents

    MPublicKeyResponse +
  • + MRequestBody +
  • +
  • MRewrapRequest
  • +
  • + MRewrapRequestBody +
  • +
  • MRewrapResponse
  • @@ -3298,6 +3318,124 @@

    KAORewrapResult.MetadataEntry

    +

    KeyAccess

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    encrypted_metadatastring

    policy_bindingbytes

    protocolstring

    key_typestring

    kas_urlstring

    kidstring

    split_idstring

    wrapped_keybytes

    headerbytes

    algorithmstring

    + + + + + +

    KeyAccessObjectRequest

    +

    + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    key_access_object_idstring

    key_access_objectKeyAccess

    + + + + +

    LegacyPublicKeyRequest

    @@ -3322,6 +3460,37 @@

    LegacyPublicKeyRequest

    +

    PolicyRequest

    +

    + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    idstring

    bodystring

    + + + + +

    PublicKeyRequest

    @@ -3391,6 +3560,37 @@

    PublicKeyResponse

    +

    RequestBody

    +

    + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    client_public_keystring

    requestsRewrapRequestBodyrepeated

    + + + + +

    RewrapRequest

    @@ -3415,6 +3615,44 @@

    RewrapRequest

    +

    RewrapRequestBody

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    key_access_object_requestsKeyAccessObjectRequestrepeated

    policyPolicyRequest

    algorithmstring

    + + + + +

    RewrapResponse

    diff --git a/protocol/go/kas/kas.pb.go b/protocol/go/kas/kas.pb.go index 16139a631..0122d1614 100644 --- a/protocol/go/kas/kas.pb.go +++ b/protocol/go/kas/kas.pb.go @@ -157,6 +157,353 @@ func (x *LegacyPublicKeyRequest) GetAlgorithm() string { return "" } +type KeyAccess struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EncryptedMetadata string `protobuf:"bytes,1,opt,name=encrypted_metadata,json=encryptedMetadata,proto3" json:"encrypted_metadata,omitempty"` + PolicyBinding []byte `protobuf:"bytes,2,opt,name=policy_binding,json=policyBinding,proto3" json:"policy_binding,omitempty"` + Protocol string `protobuf:"bytes,3,opt,name=protocol,proto3" json:"protocol,omitempty"` + KeyType string `protobuf:"bytes,4,opt,name=key_type,json=keyType,proto3" json:"key_type,omitempty"` + KasUrl string `protobuf:"bytes,5,opt,name=kas_url,json=kasUrl,proto3" json:"kas_url,omitempty"` + Kid string `protobuf:"bytes,6,opt,name=kid,proto3" json:"kid,omitempty"` + SplitId string `protobuf:"bytes,7,opt,name=split_id,json=splitId,proto3" json:"split_id,omitempty"` + WrappedKey []byte `protobuf:"bytes,8,opt,name=wrapped_key,json=wrappedKey,proto3" json:"wrapped_key,omitempty"` + Header []byte `protobuf:"bytes,9,opt,name=header,proto3" json:"header,omitempty"` + Algorithm string `protobuf:"bytes,10,opt,name=algorithm,proto3" json:"algorithm,omitempty"` +} + +func (x *KeyAccess) Reset() { + *x = KeyAccess{} + if protoimpl.UnsafeEnabled { + mi := &file_kas_kas_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyAccess) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyAccess) ProtoMessage() {} + +func (x *KeyAccess) ProtoReflect() protoreflect.Message { + mi := &file_kas_kas_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use KeyAccess.ProtoReflect.Descriptor instead. +func (*KeyAccess) Descriptor() ([]byte, []int) { + return file_kas_kas_proto_rawDescGZIP(), []int{3} +} + +func (x *KeyAccess) GetEncryptedMetadata() string { + if x != nil { + return x.EncryptedMetadata + } + return "" +} + +func (x *KeyAccess) GetPolicyBinding() []byte { + if x != nil { + return x.PolicyBinding + } + return nil +} + +func (x *KeyAccess) GetProtocol() string { + if x != nil { + return x.Protocol + } + return "" +} + +func (x *KeyAccess) GetKeyType() string { + if x != nil { + return x.KeyType + } + return "" +} + +func (x *KeyAccess) GetKasUrl() string { + if x != nil { + return x.KasUrl + } + return "" +} + +func (x *KeyAccess) GetKid() string { + if x != nil { + return x.Kid + } + return "" +} + +func (x *KeyAccess) GetSplitId() string { + if x != nil { + return x.SplitId + } + return "" +} + +func (x *KeyAccess) GetWrappedKey() []byte { + if x != nil { + return x.WrappedKey + } + return nil +} + +func (x *KeyAccess) GetHeader() []byte { + if x != nil { + return x.Header + } + return nil +} + +func (x *KeyAccess) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +type PolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *PolicyRequest) Reset() { + *x = PolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_kas_kas_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyRequest) ProtoMessage() {} + +func (x *PolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_kas_kas_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyRequest.ProtoReflect.Descriptor instead. +func (*PolicyRequest) Descriptor() ([]byte, []int) { + return file_kas_kas_proto_rawDescGZIP(), []int{4} +} + +func (x *PolicyRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *PolicyRequest) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +type KeyAccessObjectRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + KeyAccessObjectId string `protobuf:"bytes,1,opt,name=key_access_object_id,json=keyAccessObjectId,proto3" json:"key_access_object_id,omitempty"` + KeyAccessObject *KeyAccess `protobuf:"bytes,2,opt,name=key_access_object,json=keyAccessObject,proto3" json:"key_access_object,omitempty"` +} + +func (x *KeyAccessObjectRequest) Reset() { + *x = KeyAccessObjectRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_kas_kas_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyAccessObjectRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyAccessObjectRequest) ProtoMessage() {} + +func (x *KeyAccessObjectRequest) ProtoReflect() protoreflect.Message { + mi := &file_kas_kas_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use KeyAccessObjectRequest.ProtoReflect.Descriptor instead. +func (*KeyAccessObjectRequest) Descriptor() ([]byte, []int) { + return file_kas_kas_proto_rawDescGZIP(), []int{5} +} + +func (x *KeyAccessObjectRequest) GetKeyAccessObjectId() string { + if x != nil { + return x.KeyAccessObjectId + } + return "" +} + +func (x *KeyAccessObjectRequest) GetKeyAccessObject() *KeyAccess { + if x != nil { + return x.KeyAccessObject + } + return nil +} + +type RewrapRequestBody struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + KeyAccessObjectRequests []*KeyAccessObjectRequest `protobuf:"bytes,1,rep,name=key_access_object_requests,json=keyAccessObjectRequests,proto3" json:"key_access_object_requests,omitempty"` + Policy *PolicyRequest `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"` + Algorithm string `protobuf:"bytes,3,opt,name=algorithm,proto3" json:"algorithm,omitempty"` +} + +func (x *RewrapRequestBody) Reset() { + *x = RewrapRequestBody{} + if protoimpl.UnsafeEnabled { + mi := &file_kas_kas_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RewrapRequestBody) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RewrapRequestBody) ProtoMessage() {} + +func (x *RewrapRequestBody) ProtoReflect() protoreflect.Message { + mi := &file_kas_kas_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RewrapRequestBody.ProtoReflect.Descriptor instead. +func (*RewrapRequestBody) Descriptor() ([]byte, []int) { + return file_kas_kas_proto_rawDescGZIP(), []int{6} +} + +func (x *RewrapRequestBody) GetKeyAccessObjectRequests() []*KeyAccessObjectRequest { + if x != nil { + return x.KeyAccessObjectRequests + } + return nil +} + +func (x *RewrapRequestBody) GetPolicy() *PolicyRequest { + if x != nil { + return x.Policy + } + return nil +} + +func (x *RewrapRequestBody) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +type RequestBody struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientPublicKey string `protobuf:"bytes,1,opt,name=client_public_key,json=clientPublicKey,proto3" json:"client_public_key,omitempty"` + Requests []*RewrapRequestBody `protobuf:"bytes,2,rep,name=requests,proto3" json:"requests,omitempty"` +} + +func (x *RequestBody) Reset() { + *x = RequestBody{} + if protoimpl.UnsafeEnabled { + mi := &file_kas_kas_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestBody) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestBody) ProtoMessage() {} + +func (x *RequestBody) ProtoReflect() protoreflect.Message { + mi := &file_kas_kas_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestBody.ProtoReflect.Descriptor instead. +func (*RequestBody) Descriptor() ([]byte, []int) { + return file_kas_kas_proto_rawDescGZIP(), []int{7} +} + +func (x *RequestBody) GetClientPublicKey() string { + if x != nil { + return x.ClientPublicKey + } + return "" +} + +func (x *RequestBody) GetRequests() []*RewrapRequestBody { + if x != nil { + return x.Requests + } + return nil +} + type PublicKeyRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -170,7 +517,7 @@ type PublicKeyRequest struct { func (x *PublicKeyRequest) Reset() { *x = PublicKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_kas_kas_proto_msgTypes[3] + mi := &file_kas_kas_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -183,7 +530,7 @@ func (x *PublicKeyRequest) String() string { func (*PublicKeyRequest) ProtoMessage() {} func (x *PublicKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_kas_kas_proto_msgTypes[3] + mi := &file_kas_kas_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -196,7 +543,7 @@ func (x *PublicKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicKeyRequest.ProtoReflect.Descriptor instead. func (*PublicKeyRequest) Descriptor() ([]byte, []int) { - return file_kas_kas_proto_rawDescGZIP(), []int{3} + return file_kas_kas_proto_rawDescGZIP(), []int{8} } func (x *PublicKeyRequest) GetAlgorithm() string { @@ -232,7 +579,7 @@ type PublicKeyResponse struct { func (x *PublicKeyResponse) Reset() { *x = PublicKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_kas_kas_proto_msgTypes[4] + mi := &file_kas_kas_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -245,7 +592,7 @@ func (x *PublicKeyResponse) String() string { func (*PublicKeyResponse) ProtoMessage() {} func (x *PublicKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_kas_kas_proto_msgTypes[4] + mi := &file_kas_kas_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -258,7 +605,7 @@ func (x *PublicKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicKeyResponse.ProtoReflect.Descriptor instead. func (*PublicKeyResponse) Descriptor() ([]byte, []int) { - return file_kas_kas_proto_rawDescGZIP(), []int{4} + return file_kas_kas_proto_rawDescGZIP(), []int{9} } func (x *PublicKeyResponse) GetPublicKey() string { @@ -286,7 +633,7 @@ type RewrapRequest struct { func (x *RewrapRequest) Reset() { *x = RewrapRequest{} if protoimpl.UnsafeEnabled { - mi := &file_kas_kas_proto_msgTypes[5] + mi := &file_kas_kas_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -299,7 +646,7 @@ func (x *RewrapRequest) String() string { func (*RewrapRequest) ProtoMessage() {} func (x *RewrapRequest) ProtoReflect() protoreflect.Message { - mi := &file_kas_kas_proto_msgTypes[5] + mi := &file_kas_kas_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -312,7 +659,7 @@ func (x *RewrapRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RewrapRequest.ProtoReflect.Descriptor instead. func (*RewrapRequest) Descriptor() ([]byte, []int) { - return file_kas_kas_proto_rawDescGZIP(), []int{5} + return file_kas_kas_proto_rawDescGZIP(), []int{10} } func (x *RewrapRequest) GetSignedRequestToken() string { @@ -340,7 +687,7 @@ type KAORewrapResult struct { func (x *KAORewrapResult) Reset() { *x = KAORewrapResult{} if protoimpl.UnsafeEnabled { - mi := &file_kas_kas_proto_msgTypes[6] + mi := &file_kas_kas_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -353,7 +700,7 @@ func (x *KAORewrapResult) String() string { func (*KAORewrapResult) ProtoMessage() {} func (x *KAORewrapResult) ProtoReflect() protoreflect.Message { - mi := &file_kas_kas_proto_msgTypes[6] + mi := &file_kas_kas_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -366,7 +713,7 @@ func (x *KAORewrapResult) ProtoReflect() protoreflect.Message { // Deprecated: Use KAORewrapResult.ProtoReflect.Descriptor instead. func (*KAORewrapResult) Descriptor() ([]byte, []int) { - return file_kas_kas_proto_rawDescGZIP(), []int{6} + return file_kas_kas_proto_rawDescGZIP(), []int{11} } func (x *KAORewrapResult) GetMetadata() map[string]*structpb.Value { @@ -439,7 +786,7 @@ type RewrapResult struct { func (x *RewrapResult) Reset() { *x = RewrapResult{} if protoimpl.UnsafeEnabled { - mi := &file_kas_kas_proto_msgTypes[7] + mi := &file_kas_kas_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -452,7 +799,7 @@ func (x *RewrapResult) String() string { func (*RewrapResult) ProtoMessage() {} func (x *RewrapResult) ProtoReflect() protoreflect.Message { - mi := &file_kas_kas_proto_msgTypes[7] + mi := &file_kas_kas_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -465,7 +812,7 @@ func (x *RewrapResult) ProtoReflect() protoreflect.Message { // Deprecated: Use RewrapResult.ProtoReflect.Descriptor instead. func (*RewrapResult) Descriptor() ([]byte, []int) { - return file_kas_kas_proto_rawDescGZIP(), []int{7} + return file_kas_kas_proto_rawDescGZIP(), []int{12} } func (x *RewrapResult) GetPolicyId() string { @@ -501,7 +848,7 @@ type RewrapResponse struct { func (x *RewrapResponse) Reset() { *x = RewrapResponse{} if protoimpl.UnsafeEnabled { - mi := &file_kas_kas_proto_msgTypes[8] + mi := &file_kas_kas_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -514,7 +861,7 @@ func (x *RewrapResponse) String() string { func (*RewrapResponse) ProtoMessage() {} func (x *RewrapResponse) ProtoReflect() protoreflect.Message { - mi := &file_kas_kas_proto_msgTypes[8] + mi := &file_kas_kas_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -527,7 +874,7 @@ func (x *RewrapResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RewrapResponse.ProtoReflect.Descriptor instead. func (*RewrapResponse) Descriptor() ([]byte, []int) { - return file_kas_kas_proto_rawDescGZIP(), []int{8} + return file_kas_kas_proto_rawDescGZIP(), []int{13} } func (x *RewrapResponse) GetMetadata() map[string]*structpb.Value { @@ -585,110 +932,160 @@ var file_kas_kas_proto_rawDesc = []byte{ 0x61, 0x63, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, - 0x6d, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x51, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, - 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0x92, 0x41, 0x30, 0x32, 0x2e, - 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x72, - 0x73, 0x61, 0x3a, 0x3c, 0x6b, 0x65, 0x79, 0x73, 0x69, 0x7a, 0x65, 0x3e, 0x20, 0x6f, 0x72, 0x20, - 0x65, 0x63, 0x3a, 0x3c, 0x63, 0x75, 0x72, 0x76, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x3e, 0x52, 0x09, - 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x26, 0x0a, 0x03, 0x66, 0x6d, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0x92, 0x41, 0x11, 0x32, 0x0f, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x03, 0x66, 0x6d, - 0x74, 0x12, 0x22, 0x0a, 0x01, 0x76, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0x92, 0x41, - 0x11, 0x32, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x01, 0x76, 0x22, 0x44, 0x0a, 0x11, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x22, 0x4f, 0x0a, 0x0d, 0x52, - 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x14, - 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4a, 0x04, - 0x08, 0x02, 0x10, 0x03, 0x52, 0x06, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x22, 0xbb, 0x02, 0x0a, - 0x0f, 0x4b, 0x41, 0x4f, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x12, 0x3e, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4b, 0x41, 0x4f, 0x52, 0x65, 0x77, 0x72, - 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x2f, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, - 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x6b, 0x61, 0x73, - 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0d, 0x6b, 0x61, 0x73, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x53, 0x0a, 0x0d, 0x4d, + 0x6d, 0x22, 0xb5, 0x02, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, + 0x2d, 0x0a, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, + 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x69, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x6b, 0x61, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, + 0x61, 0x73, 0x55, 0x72, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x6c, 0x69, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x6c, 0x69, 0x74, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, + 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x61, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, 0x33, 0x0a, 0x0d, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x85, + 0x01, 0x0a, 0x16, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x6b, 0x65, 0x79, + 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x11, 0x6b, 0x65, + 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xb7, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x77, 0x72, 0x61, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x58, 0x0a, 0x1a, + 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x17, 0x6b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x22, 0x6d, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x08, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, + 0xb1, 0x01, 0x0a, 0x10, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x51, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0x92, 0x41, 0x30, 0x32, 0x2e, 0x61, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x72, 0x73, 0x61, + 0x3a, 0x3c, 0x6b, 0x65, 0x79, 0x73, 0x69, 0x7a, 0x65, 0x3e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x63, + 0x3a, 0x3c, 0x63, 0x75, 0x72, 0x76, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x3e, 0x52, 0x09, 0x61, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x26, 0x0a, 0x03, 0x66, 0x6d, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0x92, 0x41, 0x11, 0x32, 0x0f, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x03, 0x66, 0x6d, 0x74, 0x12, + 0x22, 0x0a, 0x01, 0x76, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0x92, 0x41, 0x11, 0x32, + 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x01, 0x76, 0x22, 0x44, 0x0a, 0x11, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x22, 0x4f, 0x0a, 0x0d, 0x52, 0x65, 0x77, + 0x72, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4a, 0x04, 0x08, 0x02, + 0x10, 0x03, 0x52, 0x06, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x22, 0xbb, 0x02, 0x0a, 0x0f, 0x4b, + 0x41, 0x4f, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3e, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4b, 0x41, 0x4f, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, + 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x6b, 0x61, 0x73, 0x5f, 0x77, + 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, + 0x48, 0x00, 0x52, 0x0d, 0x6b, 0x61, 0x73, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4b, 0x65, + 0x79, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x53, 0x0a, 0x0d, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 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, 0x42, 0x08, + 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x5b, 0x0a, 0x0c, 0x52, 0x65, 0x77, 0x72, + 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4b, 0x41, 0x4f, + 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0xd8, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6b, 0x61, 0x73, + 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x72, 0x61, 0x70, 0x70, + 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x4b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x09, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x53, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 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, - 0x42, 0x08, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x5b, 0x0a, 0x0c, 0x52, 0x65, - 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x4b, - 0x41, 0x4f, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0xd8, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x77, 0x72, - 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6b, - 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x57, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x09, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x6b, 0x61, 0x73, 0x2e, 0x52, 0x65, 0x77, 0x72, 0x61, 0x70, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x53, 0x0a, - 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 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, 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, 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, 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, + 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, 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, 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 ( @@ -703,40 +1100,49 @@ func file_kas_kas_proto_rawDescGZIP() []byte { return file_kas_kas_proto_rawDescData } -var file_kas_kas_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_kas_kas_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_kas_kas_proto_goTypes = []interface{}{ (*InfoRequest)(nil), // 0: kas.InfoRequest (*InfoResponse)(nil), // 1: kas.InfoResponse (*LegacyPublicKeyRequest)(nil), // 2: kas.LegacyPublicKeyRequest - (*PublicKeyRequest)(nil), // 3: kas.PublicKeyRequest - (*PublicKeyResponse)(nil), // 4: kas.PublicKeyResponse - (*RewrapRequest)(nil), // 5: kas.RewrapRequest - (*KAORewrapResult)(nil), // 6: kas.KAORewrapResult - (*RewrapResult)(nil), // 7: kas.RewrapResult - (*RewrapResponse)(nil), // 8: kas.RewrapResponse - nil, // 9: kas.KAORewrapResult.MetadataEntry - nil, // 10: kas.RewrapResponse.MetadataEntry - (*structpb.Value)(nil), // 11: google.protobuf.Value - (*wrapperspb.StringValue)(nil), // 12: google.protobuf.StringValue + (*KeyAccess)(nil), // 3: kas.KeyAccess + (*PolicyRequest)(nil), // 4: kas.PolicyRequest + (*KeyAccessObjectRequest)(nil), // 5: kas.KeyAccessObjectRequest + (*RewrapRequestBody)(nil), // 6: kas.RewrapRequestBody + (*RequestBody)(nil), // 7: kas.RequestBody + (*PublicKeyRequest)(nil), // 8: kas.PublicKeyRequest + (*PublicKeyResponse)(nil), // 9: kas.PublicKeyResponse + (*RewrapRequest)(nil), // 10: kas.RewrapRequest + (*KAORewrapResult)(nil), // 11: kas.KAORewrapResult + (*RewrapResult)(nil), // 12: kas.RewrapResult + (*RewrapResponse)(nil), // 13: kas.RewrapResponse + nil, // 14: kas.KAORewrapResult.MetadataEntry + nil, // 15: kas.RewrapResponse.MetadataEntry + (*structpb.Value)(nil), // 16: google.protobuf.Value + (*wrapperspb.StringValue)(nil), // 17: google.protobuf.StringValue } var file_kas_kas_proto_depIdxs = []int32{ - 9, // 0: kas.KAORewrapResult.metadata:type_name -> kas.KAORewrapResult.MetadataEntry - 6, // 1: kas.RewrapResult.results:type_name -> kas.KAORewrapResult - 10, // 2: kas.RewrapResponse.metadata:type_name -> kas.RewrapResponse.MetadataEntry - 7, // 3: kas.RewrapResponse.responses:type_name -> kas.RewrapResult - 11, // 4: kas.KAORewrapResult.MetadataEntry.value:type_name -> google.protobuf.Value - 11, // 5: kas.RewrapResponse.MetadataEntry.value:type_name -> google.protobuf.Value - 3, // 6: kas.AccessService.PublicKey:input_type -> kas.PublicKeyRequest - 2, // 7: kas.AccessService.LegacyPublicKey:input_type -> kas.LegacyPublicKeyRequest - 5, // 8: kas.AccessService.Rewrap:input_type -> kas.RewrapRequest - 4, // 9: kas.AccessService.PublicKey:output_type -> kas.PublicKeyResponse - 12, // 10: kas.AccessService.LegacyPublicKey:output_type -> google.protobuf.StringValue - 8, // 11: kas.AccessService.Rewrap:output_type -> kas.RewrapResponse - 9, // [9:12] is the sub-list for method output_type - 6, // [6:9] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 3, // 0: kas.KeyAccessObjectRequest.key_access_object:type_name -> kas.KeyAccess + 5, // 1: kas.RewrapRequestBody.key_access_object_requests:type_name -> kas.KeyAccessObjectRequest + 4, // 2: kas.RewrapRequestBody.policy:type_name -> kas.PolicyRequest + 6, // 3: kas.RequestBody.requests:type_name -> kas.RewrapRequestBody + 14, // 4: kas.KAORewrapResult.metadata:type_name -> kas.KAORewrapResult.MetadataEntry + 11, // 5: kas.RewrapResult.results:type_name -> kas.KAORewrapResult + 15, // 6: kas.RewrapResponse.metadata:type_name -> kas.RewrapResponse.MetadataEntry + 12, // 7: kas.RewrapResponse.responses:type_name -> kas.RewrapResult + 16, // 8: kas.KAORewrapResult.MetadataEntry.value:type_name -> google.protobuf.Value + 16, // 9: kas.RewrapResponse.MetadataEntry.value:type_name -> google.protobuf.Value + 8, // 10: kas.AccessService.PublicKey:input_type -> kas.PublicKeyRequest + 2, // 11: kas.AccessService.LegacyPublicKey:input_type -> kas.LegacyPublicKeyRequest + 10, // 12: kas.AccessService.Rewrap:input_type -> kas.RewrapRequest + 9, // 13: kas.AccessService.PublicKey:output_type -> kas.PublicKeyResponse + 17, // 14: kas.AccessService.LegacyPublicKey:output_type -> google.protobuf.StringValue + 13, // 15: kas.AccessService.Rewrap:output_type -> kas.RewrapResponse + 13, // [13:16] is the sub-list for method output_type + 10, // [10:13] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_kas_kas_proto_init() } @@ -782,7 +1188,7 @@ func file_kas_kas_proto_init() { } } file_kas_kas_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PublicKeyRequest); i { + switch v := v.(*KeyAccess); i { case 0: return &v.state case 1: @@ -794,7 +1200,7 @@ func file_kas_kas_proto_init() { } } file_kas_kas_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PublicKeyResponse); i { + switch v := v.(*PolicyRequest); i { case 0: return &v.state case 1: @@ -806,7 +1212,7 @@ func file_kas_kas_proto_init() { } } file_kas_kas_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RewrapRequest); i { + switch v := v.(*KeyAccessObjectRequest); i { case 0: return &v.state case 1: @@ -818,7 +1224,7 @@ func file_kas_kas_proto_init() { } } file_kas_kas_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KAORewrapResult); i { + switch v := v.(*RewrapRequestBody); i { case 0: return &v.state case 1: @@ -830,7 +1236,7 @@ func file_kas_kas_proto_init() { } } file_kas_kas_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RewrapResult); i { + switch v := v.(*RequestBody); i { case 0: return &v.state case 1: @@ -842,6 +1248,66 @@ func file_kas_kas_proto_init() { } } file_kas_kas_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kas_kas_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicKeyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kas_kas_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RewrapRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kas_kas_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KAORewrapResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kas_kas_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RewrapResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kas_kas_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RewrapResponse); i { case 0: return &v.state @@ -854,7 +1320,7 @@ func file_kas_kas_proto_init() { } } } - file_kas_kas_proto_msgTypes[6].OneofWrappers = []interface{}{ + file_kas_kas_proto_msgTypes[11].OneofWrappers = []interface{}{ (*KAORewrapResult_KasWrappedKey)(nil), (*KAORewrapResult_Error)(nil), } @@ -864,7 +1330,7 @@ func file_kas_kas_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_kas_kas_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, diff --git a/sdk/bulk.go b/sdk/bulk.go index d0fdfc479..05d6d8e54 100644 --- a/sdk/bulk.go +++ b/sdk/bulk.go @@ -6,7 +6,7 @@ import ( "fmt" "io" - "github.com/opentdf/platform/service/kas/request" + "github.com/opentdf/platform/protocol/go/kas" ) type BulkTDF struct { @@ -63,7 +63,7 @@ func (s SDK) createDecryptor(tdf *BulkTDF, tdfType TdfType) (Decryptor, error) { // BulkDecrypt func (s SDK) BulkDecrypt(ctx context.Context, bulkReq *BulkDecryptRequest) error { - kasRewrapRequests := make(map[string][]*request.RewrapRequests) + kasRewrapRequests := make(map[string][]*kas.RewrapRequestBody) tdfDecryptors := make(map[string]Decryptor) policyTDF := make(map[string]*BulkTDF) @@ -83,7 +83,7 @@ func (s SDK) BulkDecrypt(ctx context.Context, bulkReq *BulkDecryptRequest) error tdfDecryptors[policyID] = decryptor policyTDF[policyID] = tdf for kasURL, r := range req { - r.Policy.ID = policyID + r.Policy.Id = policyID kasRewrapRequests[kasURL] = append(kasRewrapRequests[kasURL], r) } } diff --git a/sdk/kas_client.go b/sdk/kas_client.go index d2b11fbda..9132767a0 100644 --- a/sdk/kas_client.go +++ b/sdk/kas_client.go @@ -2,19 +2,19 @@ package sdk import ( "context" - "encoding/json" "errors" "fmt" "net" "net/url" "time" + "google.golang.org/protobuf/encoding/protojson" + "github.com/lestrrat-go/jwx/v2/jwk" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/lib/ocrypto" "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/sdk/auth" - "github.com/opentdf/platform/service/kas/request" "google.golang.org/grpc" ) @@ -35,7 +35,7 @@ type KAOResult struct { } type Decryptor interface { - CreateRewrapRequest(ctx context.Context) (map[string]*request.RewrapRequests, error) + CreateRewrapRequest(ctx context.Context) (map[string]*kas.RewrapRequestBody, error) Decrypt(ctx context.Context, results []KAOResult) (uint32, error) } @@ -48,12 +48,12 @@ func newKASClient(dialOptions []grpc.DialOption, accessTokenSource auth.AccessTo } // there is no connection caching as of now -func (k *KASClient) makeRewrapRequest(ctx context.Context, requests []*request.RewrapRequests, pubKey string) (*kas.RewrapResponse, error) { +func (k *KASClient) makeRewrapRequest(ctx context.Context, requests []*kas.RewrapRequestBody, pubKey string) (*kas.RewrapResponse, error) { rewrapRequest, err := k.getRewrapRequest(requests, pubKey) if err != nil { return nil, err } - grpcAddress, err := getGRPCAddress(requests[0].KeyAccessObjectRequests[0].KasURL) + grpcAddress, err := getGRPCAddress(requests[0].GetKeyAccessObjectRequests()[0].GetKeyAccessObject().GetKasUrl()) if err != nil { return nil, err } @@ -73,7 +73,7 @@ func (k *KASClient) makeRewrapRequest(ctx context.Context, requests []*request.R return response, nil } -func (k *KASClient) nanoUnwrap(ctx context.Context, requests ...*request.RewrapRequests) (map[string][]KAOResult, error) { +func (k *KASClient) nanoUnwrap(ctx context.Context, requests ...*kas.RewrapRequestBody) (map[string][]KAOResult, error) { keypair, err := ocrypto.NewECKeyPair(ocrypto.ECCModeSecp256r1) if err != nil { return nil, fmt.Errorf("ocrypto.NewECKeyPair failed :%w", err) @@ -112,7 +112,7 @@ func (k *KASClient) nanoUnwrap(ctx context.Context, requests ...*request.RewrapR for _, results := range response.GetResponses() { var kaoKeys []KAOResult for _, kao := range results.GetResults() { - if kao.GetStatus() == request.PermitStatus { + if kao.GetStatus() == "permit" { wrappedKey := kao.GetKasWrappedKey() key, err := aesGcm.Decrypt(wrappedKey) if err != nil { @@ -130,7 +130,7 @@ func (k *KASClient) nanoUnwrap(ctx context.Context, requests ...*request.RewrapR return policyResults, nil } -func (k *KASClient) unwrap(ctx context.Context, requests ...*request.RewrapRequests) (map[string][]KAOResult, error) { +func (k *KASClient) unwrap(ctx context.Context, requests ...*kas.RewrapRequestBody) (map[string][]KAOResult, error) { if k.sessionKey == nil { return nil, fmt.Errorf("session key is nil") } @@ -157,7 +157,7 @@ func (k *KASClient) unwrap(ctx context.Context, requests ...*request.RewrapReque for _, results := range response.GetResponses() { var kaoKeys []KAOResult for _, kao := range results.GetResults() { - if kao.GetStatus() == request.PermitStatus { + if kao.GetStatus() == "permit" { wrappedKey := kao.GetKasWrappedKey() key, err := asymDecryption.Decrypt(wrappedKey) if err != nil { @@ -195,13 +195,13 @@ func getGRPCAddress(kasURL string) (string, error) { return net.JoinHostPort(parsedURL.Hostname(), port), nil } -func (k *KASClient) getRewrapRequest(reqs []*request.RewrapRequests, pubKey string) (*kas.RewrapRequest, error) { - requestBody := request.Body{ +func (k *KASClient) getRewrapRequest(reqs []*kas.RewrapRequestBody, pubKey string) (*kas.RewrapRequest, error) { + requestBody := &kas.RequestBody{ ClientPublicKey: pubKey, Requests: reqs, } - requestBodyJSON, err := json.Marshal(requestBody) + requestBodyJSON, err := protojson.Marshal(requestBody) if err != nil { return nil, fmt.Errorf("Error marshaling request body: %w", err) } diff --git a/sdk/kas_client_test.go b/sdk/kas_client_test.go index 0590b504c..39287e6a1 100644 --- a/sdk/kas_client_test.go +++ b/sdk/kas_client_test.go @@ -6,7 +6,8 @@ import ( "net/http" "testing" - "github.com/opentdf/platform/service/kas/request" + kaspb "github.com/opentdf/platform/protocol/go/kas" + "google.golang.org/protobuf/encoding/protojson" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" @@ -59,20 +60,22 @@ func TestCreatingRequest(t *testing.T) { require.NoError(t, err, "error creating RSA Key") client := newKASClient(dialOption, tokenSource, &kasKey) + policyBindingBytes, err := json.Marshal(PolicyBinding{ + Alg: "HS256", + Hash: "somehash", + }) + require.NoError(t, err) - keyAccess := []*request.RewrapRequests{ + keyAccess := []*kaspb.RewrapRequestBody{ { - KeyAccessObjectRequests: []*request.KeyAccessObjectRequest{ + KeyAccessObjectRequests: []*kaspb.KeyAccessObjectRequest{ { - KeyAccess: request.KeyAccess{ - KeyType: "type1", - KasURL: "https://kas.example.org", - Protocol: "protocol one", - WrappedKey: []byte("wrapped"), - PolicyBinding: PolicyBinding{ - Alg: "HS256", - Hash: "somehash", - }, + KeyAccessObject: &kaspb.KeyAccess{ + KeyType: "type1", + KasUrl: "https://kas.example.org", + Protocol: "protocol one", + WrappedKey: []byte("wrapped"), + PolicyBinding: policyBindingBytes, EncryptedMetadata: "encrypted", }, }, @@ -98,25 +101,26 @@ func TestCreatingRequest(t *testing.T) { rb, ok := tok.Get("requestBody") require.True(t, ok, "didn't contain a request body") requestBodyJSON, _ := rb.(string) - var requestBody request.Body + var requestBody kaspb.RequestBody - require.NoError(t, json.Unmarshal([]byte(requestBodyJSON), &requestBody), "error unmarshaling request body") + require.NoError(t, protojson.Unmarshal([]byte(requestBodyJSON), &requestBody), "error unmarshaling request body") - _, err = ocrypto.NewAsymEncryption(requestBody.ClientPublicKey) + _, err = ocrypto.NewAsymEncryption(requestBody.GetClientPublicKey()) require.NoError(t, err, "NewAsymEncryption failed, incorrect public key include") - require.Len(t, requestBody.Requests, 1) - require.Len(t, requestBody.Requests[0].KeyAccessObjectRequests, 1) - kao := requestBody.Requests[0].KeyAccessObjectRequests[0] - policyBinding, ok := kao.PolicyBinding.(map[string]interface{}) - require.True(t, ok, "invalid policy binding") + require.Len(t, requestBody.GetRequests(), 1) + require.Len(t, requestBody.GetRequests()[0].GetKeyAccessObjectRequests(), 1) + kao := requestBody.GetRequests()[0].GetKeyAccessObjectRequests()[0] + var policyBinding map[string]interface{} + err = json.Unmarshal(kao.GetKeyAccessObject().GetPolicyBinding(), &policyBinding) + require.NoError(t, err) - assert.Equal(t, "https://kas.example.org", kao.KasURL, "incorrect kasURL") - assert.Equal(t, "protocol one", kao.Protocol, "incorrect protocol") - assert.Equal(t, []byte("wrapped"), kao.WrappedKey, "incorrect wrapped key") + assert.Equal(t, "https://kas.example.org", kao.GetKeyAccessObject().GetKasUrl(), "incorrect kasURL") + assert.Equal(t, "protocol one", kao.GetKeyAccessObject().GetProtocol(), "incorrect protocol") + assert.Equal(t, []byte("wrapped"), kao.GetKeyAccessObject().GetWrappedKey(), "incorrect wrapped key") assert.Equal(t, "HS256", policyBinding["alg"], "incorrect policy binding") assert.Equal(t, "somehash", policyBinding["hash"], "incorrect policy binding") - assert.Equal(t, "encrypted", kao.EncryptedMetadata, "incorrect encrypted metadata") + assert.Equal(t, "encrypted", kao.GetKeyAccessObject().GetEncryptedMetadata(), "incorrect encrypted metadata") } func Test_StoreKASKeys(t *testing.T) { diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index aff0ad022..6ffc6c577 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -14,7 +14,7 @@ import ( "sync" "time" - "github.com/opentdf/platform/service/kas/request" + "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/lib/ocrypto" ) @@ -920,7 +920,7 @@ func (n *NanoTDFDecryptHandler) getRawHeader() []byte { return n.headerBuf } -func (n *NanoTDFDecryptHandler) CreateRewrapRequest(_ context.Context) (map[string]*request.RewrapRequests, error) { +func (n *NanoTDFDecryptHandler) CreateRewrapRequest(_ context.Context) (map[string]*kas.RewrapRequestBody, error) { var err error var headerSize uint32 n.header, headerSize, err = NewNanoTDFHeaderFromReader(n.reader) @@ -942,19 +942,19 @@ func (n *NanoTDFDecryptHandler) CreateRewrapRequest(_ context.Context) (map[stri return nil, err } - req := &request.RewrapRequests{ - KeyAccessObjectRequests: []*request.KeyAccessObjectRequest{ + req := &kas.RewrapRequestBody{ + KeyAccessObjectRequests: []*kas.KeyAccessObjectRequest{ { - KeyAccessObjectID: "kao-0", - KeyAccess: request.KeyAccess{KasURL: kasURL, Header: headerBuf, Algorithm: "ec:secp256r1"}, + KeyAccessObjectId: "kao-0", + KeyAccessObject: &kas.KeyAccess{KasUrl: kasURL, Header: headerBuf, Algorithm: "ec:secp256r1"}, }, }, - Policy: request.PolicyRequest{ - ID: "policy", + Policy: &kas.PolicyRequest{ + Id: "policy", }, Algorithm: "ec:secp256r1", } - return map[string]*request.RewrapRequests{kasURL: req}, nil + return map[string]*kas.RewrapRequestBody{kasURL: req}, nil } func (n *NanoTDFDecryptHandler) Decrypt(_ context.Context, result []KAOResult) (uint32, error) { diff --git a/sdk/tdf.go b/sdk/tdf.go index bb92415ac..8b59a55d8 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -12,7 +12,7 @@ import ( "strconv" "strings" - "github.com/opentdf/platform/service/kas/request" + "github.com/opentdf/platform/protocol/go/kas" "github.com/google/uuid" "github.com/opentdf/platform/lib/ocrypto" @@ -94,7 +94,7 @@ func (r *tdf3DecryptHandler) Decrypt(ctx context.Context, results []KAOResult) ( return uint32(n), err } -func (r *tdf3DecryptHandler) CreateRewrapRequest(ctx context.Context) (map[string]*request.RewrapRequests, error) { +func (r *tdf3DecryptHandler) CreateRewrapRequest(ctx context.Context) (map[string]*kas.RewrapRequestBody, error) { return createRewrapRequest(ctx, r.reader) } @@ -821,36 +821,39 @@ func (r *Reader) UnsafePayloadKeyRetrieval() ([]byte, error) { return r.payloadKey, nil } -func createRewrapRequest(_ context.Context, r *Reader) (map[string]*request.RewrapRequests, error) { - kasReqs := make(map[string]*request.RewrapRequests) +func createRewrapRequest(_ context.Context, r *Reader) (map[string]*kas.RewrapRequestBody, error) { + kasReqs := make(map[string]*kas.RewrapRequestBody) for i, kao := range r.manifest.EncryptionInformation.KeyAccessObjs { kaoID := fmt.Sprintf("kao-%d", i) key, err := ocrypto.Base64Decode([]byte(kao.WrappedKey)) if err != nil { return nil, fmt.Errorf("could not decode wrapper key: %w", err) } - - kaoReq := &request.KeyAccessObjectRequest{ - KeyAccessObjectID: kaoID, - KeyAccess: request.KeyAccess{ + binding, err := json.Marshal(kao.PolicyBinding) + if err != nil { + return nil, err + } + kaoReq := &kas.KeyAccessObjectRequest{ + KeyAccessObjectId: kaoID, + KeyAccessObject: &kas.KeyAccess{ KeyType: kao.KeyType, - KasURL: kao.KasURL, - KID: kao.KID, + KasUrl: kao.KasURL, + Kid: kao.KID, Protocol: kao.Protocol, - PolicyBinding: kao.PolicyBinding, - SplitID: kao.SplitID, + PolicyBinding: binding, + SplitId: kao.SplitID, WrappedKey: key, }, } if req, ok := kasReqs[kao.KasURL]; ok { req.KeyAccessObjectRequests = append(req.KeyAccessObjectRequests, kaoReq) } else { - rewrapReq := request.RewrapRequests{ - Policy: request.PolicyRequest{ + rewrapReq := kas.RewrapRequestBody{ + Policy: &kas.PolicyRequest{ Body: r.manifest.EncryptionInformation.Policy, - ID: "policy", + Id: "policy", }, - KeyAccessObjectRequests: []*request.KeyAccessObjectRequest{kaoReq}, + KeyAccessObjectRequests: []*kas.KeyAccessObjectRequest{kaoReq}, } kasReqs[kao.KasURL] = &rewrapReq } diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index 9a5c66ce5..08d726e19 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -6,7 +6,6 @@ import ( "crypto/rand" "crypto/rsa" "crypto/sha256" - "encoding/json" "fmt" "io" "log/slog" @@ -18,7 +17,7 @@ import ( "testing" "time" - "github.com/opentdf/platform/service/kas/request" + "google.golang.org/protobuf/encoding/protojson" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/lib/ocrypto" @@ -1439,22 +1438,23 @@ func (f *FakeKas) PublicKey(_ context.Context, _ *kaspb.PublicKeyRequest) (*kasp } func (f *FakeKas) getRewrapResponse(rewrapRequest string) *kaspb.RewrapResponse { - bodyData := request.Body{} - err := json.Unmarshal([]byte(rewrapRequest), &bodyData) + bodyData := kaspb.RequestBody{} + err := protojson.Unmarshal([]byte(rewrapRequest), &bodyData) f.s.Require().NoError(err, "json.Unmarshal failed") resp := &kaspb.RewrapResponse{} - for _, req := range bodyData.Requests { - results := &kaspb.RewrapResult{PolicyId: req.Policy.ID} + for _, req := range bodyData.GetRequests() { + results := &kaspb.RewrapResult{PolicyId: req.GetPolicy().GetId()} resp.Responses = append(resp.Responses, results) - for _, kaoReq := range req.KeyAccessObjectRequests { - wrappedKey := kaoReq.WrappedKey + for _, kaoReq := range req.GetKeyAccessObjectRequests() { + kao := kaoReq.GetKeyAccessObject() + wrappedKey := kaoReq.GetKeyAccessObject().GetWrappedKey() kasPrivateKey := strings.ReplaceAll(f.privateKey, "\n\t", "\n") - if kaoReq.KID != "" && kaoReq.KID != f.KID { + if kao.GetKid() != "" && kao.GetKid() != f.KID { // old kid - lk, ok := f.legakeys[kaoReq.KID] - f.s.Require().True(ok, "unable to find key [%s]", kaoReq.KID) + lk, ok := f.legakeys[kaoReq.GetKeyAccessObject().GetKid()] + f.s.Require().True(ok, "unable to find key [%s]", kao.GetKid()) kasPrivateKey = strings.ReplaceAll(lk.private, "\n\t", "\n") } @@ -1462,14 +1462,14 @@ func (f *FakeKas) getRewrapResponse(rewrapRequest string) *kaspb.RewrapResponse f.s.Require().NoError(err, "ocrypto.NewAsymDecryption failed") symmetricKey, err := asymDecrypt.Decrypt(wrappedKey) f.s.Require().NoError(err, "ocrypto.Decrypt failed") - asymEncrypt, err := ocrypto.NewAsymEncryption(bodyData.ClientPublicKey) + asymEncrypt, err := ocrypto.NewAsymEncryption(bodyData.GetClientPublicKey()) f.s.Require().NoError(err, "ocrypto.NewAsymEncryption failed") entityWrappedKey, err := asymEncrypt.Encrypt(symmetricKey) f.s.Require().NoError(err, "ocrypto.encrypt failed") kaoResult := &kaspb.KAORewrapResult{ Result: &kaspb.KAORewrapResult_KasWrappedKey{KasWrappedKey: entityWrappedKey}, Status: "permit", - KeyAccessObjectId: kaoReq.KeyAccessObjectID, + KeyAccessObjectId: kaoReq.GetKeyAccessObjectId(), } results.Results = append(results.Results, kaoResult) } diff --git a/service/kas/access/accessPdp.go b/service/kas/access/accessPdp.go index 07e90a047..8bdfb87e7 100644 --- a/service/kas/access/accessPdp.go +++ b/service/kas/access/accessPdp.go @@ -5,8 +5,6 @@ import ( "errors" "fmt" - "github.com/opentdf/platform/service/kas/request" - "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/policy" ) @@ -20,13 +18,13 @@ const ( type PDPAccessResult struct { Access bool Error error - Policy *request.Policy + Policy *Policy } -func (p *Provider) canAccess(ctx context.Context, token *authorization.Token, policies []*request.Policy) ([]PDPAccessResult, error) { +func (p *Provider) canAccess(ctx context.Context, token *authorization.Token, policies []*Policy) ([]PDPAccessResult, error) { var res []PDPAccessResult var rasList []*authorization.ResourceAttribute - idPolicyMap := make(map[string]*request.Policy) + idPolicyMap := make(map[string]*Policy) for i, policy := range policies { if len(policy.Body.Dissem) > 0 { // TODO: Move dissems check to the getdecisions endpoint diff --git a/service/kas/request/attribute.go b/service/kas/access/attribute.go similarity index 88% rename from service/kas/request/attribute.go rename to service/kas/access/attribute.go index 424da91ce..27c088d90 100644 --- a/service/kas/request/attribute.go +++ b/service/kas/access/attribute.go @@ -1,11 +1,9 @@ -package request +package access import ( "crypto" ) -// const schemaVersion = "1.1.0" - type Attribute struct { URI string `json:"attribute"` // attribute PublicKey crypto.PublicKey `json:"pubKey"` // pubKey diff --git a/service/kas/request/keyaccess.go b/service/kas/access/keyaccess.go similarity index 73% rename from service/kas/request/keyaccess.go rename to service/kas/access/keyaccess.go index 1bf67b922..69cd7fe21 100644 --- a/service/kas/request/keyaccess.go +++ b/service/kas/access/keyaccess.go @@ -1,13 +1,13 @@ -package request +package access type KeyAccess struct { EncryptedMetadata string `json:"encryptedMetadata,omitempty"` PolicyBinding interface{} `json:"policyBinding,omitempty"` Protocol string `json:"protocol"` - KeyType string `json:"type"` - KasURL string `json:"url"` + Type string `json:"type"` + URL string `json:"url"` KID string `json:"kid,omitempty"` - SplitID string `json:"sid,omitempty"` + SID string `json:"sid,omitempty"` WrappedKey []byte `json:"wrappedKey,omitempty"` Header []byte `json:"header,omitempty"` Algorithm string `json:"algorithm,omitempty"` diff --git a/service/kas/request/policy.go b/service/kas/access/policy.go similarity index 98% rename from service/kas/request/policy.go rename to service/kas/access/policy.go index aab7a443e..c84e19ef7 100644 --- a/service/kas/request/policy.go +++ b/service/kas/access/policy.go @@ -1,4 +1,4 @@ -package request +package access import ( "github.com/google/uuid" diff --git a/service/kas/access/rewrap.go b/service/kas/access/rewrap.go index a6dd24c85..ef015d89f 100644 --- a/service/kas/access/rewrap.go +++ b/service/kas/access/rewrap.go @@ -2,6 +2,9 @@ package access import ( "bytes" + + "google.golang.org/protobuf/encoding/protojson" + // "bytes" "context" "crypto" @@ -31,7 +34,6 @@ import ( kaspb "github.com/opentdf/platform/protocol/go/kas" "github.com/opentdf/platform/sdk" "github.com/opentdf/platform/service/internal/security" - "github.com/opentdf/platform/service/kas/request" "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/logger/audit" ctxAuth "github.com/opentdf/platform/service/pkg/auth" @@ -49,20 +51,29 @@ type SignedRequestBody struct { } type RequestBody struct { - AuthToken string `json:"authToken"` - KeyAccess request.KeyAccess `json:"keyAccess"` - Policy string `json:"policy,omitempty"` - Algorithm string `json:"algorithm,omitempty"` - ClientPublicKey string `json:"clientPublicKey"` - PublicKey interface{} `json:"-"` - SchemaVersion string `json:"schemaVersion,omitempty"` + AuthToken string `json:"authToken"` + KeyAccess kaspb.KeyAccess `json:"keyAccess"` + Policy string `json:"policy,omitempty"` + Algorithm string `json:"algorithm,omitempty"` + ClientPublicKey string `json:"clientPublicKey"` + PublicKey interface{} `json:"-"` + SchemaVersion string `json:"schemaVersion,omitempty"` } + type entityInfo struct { EntityID string `json:"sub"` ClientID string `json:"clientId"` Token string `json:"-"` } +type kaoResult struct { + ID string + Key []byte + Error error +} + +type policyKAOResults map[string]map[string]kaoResult + const ( kNanoTDFGMACLength = 8 ErrUser = Error("request error") @@ -126,32 +137,32 @@ func justRequestBody(ctx context.Context, token jwt.Token, logger logger.Logger) return rbString, nil } -func extractAndConvertV1SRTBody(body []byte) (request.Body, error) { +func extractAndConvertV1SRTBody(body []byte) (kaspb.RequestBody, error) { var requestBody RequestBody if err := json.Unmarshal(body, &requestBody); err != nil { - return request.Body{}, err + return kaspb.RequestBody{}, err } - reqs := []*request.RewrapRequests{ + reqs := []*kaspb.RewrapRequestBody{ { - KeyAccessObjectRequests: []*request.KeyAccessObjectRequest{ - {KeyAccessObjectID: "kao-0", KeyAccess: requestBody.KeyAccess}, + KeyAccessObjectRequests: []*kaspb.KeyAccessObjectRequest{ + {KeyAccessObjectId: "kao-0", KeyAccessObject: &requestBody.KeyAccess}, }, Algorithm: requestBody.Algorithm, - Policy: request.PolicyRequest{ - ID: "policy-1", + Policy: &kaspb.PolicyRequest{ + Id: "policy-1", Body: requestBody.Policy, }, }, } - return request.Body{ + return kaspb.RequestBody{ ClientPublicKey: requestBody.ClientPublicKey, Requests: reqs, }, nil } -func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRequest, logger logger.Logger) (*request.Body, bool, error) { +func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRequest, logger logger.Logger) (*kaspb.RequestBody, bool, error) { isV1 := false // First load legacy method for verifying SRT if vpk, ok := headers["X-Virtrupubkey"]; ok && len(vpk) == 1 { @@ -184,10 +195,10 @@ func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRe } } - var requestBody request.Body - err = json.Unmarshal([]byte(rbString), &requestBody) + var requestBody kaspb.RequestBody + err = protojson.Unmarshal([]byte(rbString), &requestBody) // if there are no requests then it could be a v1 request - if err != nil || len(requestBody.Requests) == 0 { + if err != nil || len(requestBody.GetRequests()) == 0 { logger.WarnContext(ctx, "invalid request body! checking v1 SRT") requestBody, err = extractAndConvertV1SRTBody([]byte(rbString)) if err != nil { @@ -195,10 +206,10 @@ func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRe } isV1 = true } - logger.DebugContext(ctx, "extracted request body", slog.Any("requestBody", requestBody)) + logger.DebugContext(ctx, "extracted request body", slog.Any("requestBody", requestBody.String())) - logger.DebugContext(ctx, "extract public key", "requestBody.ClientPublicKey", requestBody.ClientPublicKey) - block, _ := pem.Decode([]byte(requestBody.ClientPublicKey)) + logger.DebugContext(ctx, "extract public key", "requestBody.ClientPublicKey", requestBody.GetClientPublicKey()) + block, _ := pem.Decode([]byte(requestBody.GetClientPublicKey())) if block == nil { logger.WarnContext(ctx, "missing clientPublicKey") return nil, isV1, err400("clientPublicKey failure") @@ -222,13 +233,13 @@ func extractSRTBody(ctx context.Context, headers http.Header, in *kaspb.RewrapRe } } -func verifyPolicyBinding(ctx context.Context, policy []byte, kao *request.KeyAccessObjectRequest, logger logger.Logger) error { - actualHMAC, err := generateHMACDigest(ctx, policy, kao.SymmetricKey, logger) +func verifyPolicyBinding(ctx context.Context, policy []byte, kao *kaspb.KeyAccessObjectRequest, symKey []byte, logger logger.Logger) error { + actualHMAC, err := generateHMACDigest(ctx, policy, symKey, logger) if err != nil { logger.WarnContext(ctx, "unable to generate policy hmac", "err", err) return err400("bad request") } - policyBinding, err := extractPolicyBinding(kao.PolicyBinding) + policyBinding, err := extractPolicyBinding(kao.GetKeyAccessObject().GetPolicyBinding()) if err != nil { logger.WarnContext(ctx, "bad policy binding") return err400("bad request") @@ -252,7 +263,11 @@ func verifyPolicyBinding(ctx context.Context, policy []byte, kao *request.KeyAcc return nil } -func extractPolicyBinding(policyBinding interface{}) (string, error) { +func extractPolicyBinding(policyBindingBytes []byte) (string, error) { + var policyBinding interface{} + if err := json.Unmarshal(policyBindingBytes, &policyBinding); err != nil { + return "", fmt.Errorf("could not decode binding") + } switch v := policyBinding.(type) { case string: return v, nil @@ -289,27 +304,44 @@ func getEntityInfo(ctx context.Context, logger *logger.Logger) (*entityInfo, err return info, nil } -func failedKAORewrap(res *kaspb.RewrapResult, kao *request.KeyAccessObjectRequest, err error) { - if kao.Processed { - return - } - kao.Processed = true - kaoRes := &kaspb.KAORewrapResult{ - KeyAccessObjectId: kao.KeyAccessObjectID, - Status: kFailedStatus, - Result: &kaspb.KAORewrapResult_Error{Error: err.Error()}, - } - kao.Err = err - res.Results = append(res.Results, kaoRes) +func failedKAORewrap(res map[string]kaoResult, kao *kaspb.KeyAccessObjectRequest, err error) { + res[kao.GetKeyAccessObjectId()] = kaoResult{ + ID: kao.GetKeyAccessObjectId(), + Error: err, + } } -func markUnproccessedRequests(reqs []*request.RewrapRequests) { - for _, req := range reqs { - for _, kao := range req.KeyAccessObjectRequests { - failedKAORewrap(req.Results, kao, err400("could not process request")) +func addResultsToResponse(response *kaspb.RewrapResponse, result policyKAOResults) { + for policyID, policyMap := range result { + policyResults := &kaspb.RewrapResult{ + PolicyId: policyID, } + for kaoID, kaoRes := range policyMap { + kaoResult := &kaspb.KAORewrapResult{ + KeyAccessObjectId: kaoID, + } + switch { + case kaoRes.Error != nil: + kaoResult.Status = kFailedStatus + kaoResult.Result = &kaspb.KAORewrapResult_Error{Error: kaoRes.Error.Error()} + case kaoRes.Key != nil: + kaoResult.Status = kPermitStatus + kaoResult.Result = &kaspb.KAORewrapResult_KasWrappedKey{KasWrappedKey: kaoRes.Key} + default: + kaoResult.Status = kFailedStatus + kaoResult.Result = &kaspb.KAORewrapResult_Error{Error: "kao not processed by kas"} + } + policyResults.Results = append(policyResults.Results, kaoResult) + } + response.Responses = append(response.Responses, policyResults) } } +func getMapValue[Map ~map[K]V, K comparable, V any](m Map) *V { + for _, v := range m { + return &v + } + return nil +} func (p *Provider) Rewrap(ctx context.Context, req *connect.Request[kaspb.RewrapRequest]) (*connect.Response[kaspb.RewrapResponse], error) { in := req.Msg @@ -329,70 +361,65 @@ func (p *Provider) Rewrap(ctx context.Context, req *connect.Request[kaspb.Rewrap resp := &kaspb.RewrapResponse{} - var nanoReqs []*request.RewrapRequests - var tdf3Reqs []*request.RewrapRequests - var requests []*request.RewrapRequests - for _, req := range body.Requests { + var nanoReqs []*kaspb.RewrapRequestBody + var tdf3Reqs []*kaspb.RewrapRequestBody + for _, req := range body.GetRequests() { switch { - case req.Algorithm == kNanoAlgorithm: + case req.GetAlgorithm() == kNanoAlgorithm: nanoReqs = append(nanoReqs, req) - case req.Algorithm == "": + case req.GetAlgorithm() == "": req.Algorithm = kTDF3Algorithm tdf3Reqs = append(tdf3Reqs, req) default: tdf3Reqs = append(tdf3Reqs, req) } } + var results policyKAOResults if len(tdf3Reqs) > 0 { - p.tdf3Rewrap(ctx, tdf3Reqs, body.ClientPublicKey, entityInfo) - requests = append(requests, tdf3Reqs...) - } - - if len(nanoReqs) > 0 { - resp.SessionPublicKey = p.nanoTDFRewrap(ctx, nanoReqs, body.ClientPublicKey, entityInfo) - requests = append(requests, nanoReqs...) - } - - markUnproccessedRequests(requests) - for _, req := range requests { - resp.Responses = append(resp.Responses, req.Results) + results = p.tdf3Rewrap(ctx, tdf3Reqs, body.GetClientPublicKey(), entityInfo) + addResultsToResponse(resp, results) + } else { + resp.SessionPublicKey, results = p.nanoTDFRewrap(ctx, nanoReqs, body.GetClientPublicKey(), entityInfo) + addResultsToResponse(resp, results) } if isV1 { - if len(resp.GetResponses()) != 1 || len(resp.GetResponses()[0].GetResults()) != 1 { + if len(results) != 1 { return nil, fmt.Errorf("invalid request") } - res := resp.GetResponses()[0].GetResults()[0] - if res.GetStatus() == kFailedStatus { - return nil, requests[0].KeyAccessObjectRequests[0].Err + kaoResults := *getMapValue(results) + if len(kaoResults) != 1 { + return nil, fmt.Errorf("invalid request") + } + kao := *getMapValue(kaoResults) + + if kao.Error != nil { + return nil, kao.Error } - resp.EntityWrappedKey = res.GetKasWrappedKey() - resp.Metadata = res.GetMetadata() + resp.EntityWrappedKey = kao.Key } return connect.NewResponse(resp), err } -func (p *Provider) verifyRewrapRequests(ctx context.Context, req *request.RewrapRequests) (*request.Policy, error) { +func (p *Provider) verifyRewrapRequests(ctx context.Context, req *kaspb.RewrapRequestBody) (*Policy, map[string]kaoResult, error) { + results := make(map[string]kaoResult) anyValidKAOs := false - p.Logger.DebugContext(ctx, "extracting policy", "requestBody.policy", req.Policy) - sDecPolicy, policyErr := base64.StdEncoding.DecodeString(req.Policy.Body) - req.Results = &kaspb.RewrapResult{ - PolicyId: req.Policy.ID, - } - policy := &request.Policy{} + p.Logger.DebugContext(ctx, "extracting policy", "requestBody.policy", req.GetPolicy()) + sDecPolicy, policyErr := base64.StdEncoding.DecodeString(req.GetPolicy().GetBody()) + policy := &Policy{} if policyErr == nil { policyErr = json.Unmarshal(sDecPolicy, policy) } - for _, kao := range req.KeyAccessObjectRequests { + for _, kao := range req.GetKeyAccessObjectRequests() { if policyErr != nil { - failedKAORewrap(req.Results, kao, err400("bad request")) + failedKAORewrap(results, kao, err400("bad request")) continue } var kidsToCheck []string - if kao.KID != "" { - kidsToCheck = []string{kao.KID} + if kao.GetKeyAccessObject().GetKid() != "" { + kidsToCheck = []string{kao.GetKeyAccessObject().GetKid()} } else { p.Logger.InfoContext(ctx, "kid free kao") for _, k := range p.KASConfig.Keyring { @@ -402,58 +429,63 @@ func (p *Provider) verifyRewrapRequests(ctx context.Context, req *request.Rewrap } if len(kidsToCheck) == 0 { p.Logger.WarnContext(ctx, "failure to find legacy kids for rsa") - failedKAORewrap(req.Results, kao, err400("bad request")) + failedKAORewrap(results, kao, err400("bad request")) continue } } - var err error - kao.SymmetricKey, err = p.CryptoProvider.RSADecrypt(crypto.SHA1, kidsToCheck[0], "", kao.WrappedKey) + symKey, err := p.CryptoProvider.RSADecrypt(crypto.SHA1, kidsToCheck[0], "", kao.GetKeyAccessObject().GetWrappedKey()) for _, kid := range kidsToCheck[1:] { p.Logger.WarnContext(ctx, "continue paging through legacy KIDs for kid free kao", "err", err) if err == nil { break } - kao.SymmetricKey, err = p.CryptoProvider.RSADecrypt(crypto.SHA1, kid, "", kao.WrappedKey) + symKey, err = p.CryptoProvider.RSADecrypt(crypto.SHA1, kid, "", kao.GetKeyAccessObject().GetWrappedKey()) } if err != nil { p.Logger.WarnContext(ctx, "failure to decrypt dek", "err", err) - failedKAORewrap(req.Results, kao, err400("bad request")) + failedKAORewrap(results, kao, err400("bad request")) continue } - err = verifyPolicyBinding(ctx, []byte(req.Policy.Body), kao, *p.Logger) + err = verifyPolicyBinding(ctx, []byte(req.GetPolicy().GetBody()), kao, symKey, *p.Logger) if err != nil { - failedKAORewrap(req.Results, kao, err) + failedKAORewrap(results, kao, err) continue } + results[kao.GetKeyAccessObjectId()] = kaoResult{ + ID: kao.GetKeyAccessObjectId(), + Key: symKey, + } anyValidKAOs = true } if policyErr != nil { - return nil, policyErr + return nil, results, policyErr } if !anyValidKAOs { p.Logger.WarnContext(ctx, "no valid KAOs found") - return policy, fmt.Errorf("no valid KAOs") + return policy, results, fmt.Errorf("no valid KAOs") } - return policy, nil + return policy, results, nil } -func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*request.RewrapRequests, clientPublicKey string, entity *entityInfo) { +func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*kaspb.RewrapRequestBody, clientPublicKey string, entity *entityInfo) policyKAOResults { if p.Tracer != nil { var span trace.Span ctx, span = p.Tracer.Start(ctx, "rewrap-tdf3") defer span.End() } - var policies []*request.Policy - policyReqs := make(map[*request.Policy]*request.RewrapRequests) + results := make(policyKAOResults) + var policies []*Policy + policyReqs := make(map[*Policy]*kaspb.RewrapRequestBody) for _, req := range requests { - policy, err := p.verifyRewrapRequests(ctx, req) + policy, kaoResults, err := p.verifyRewrapRequests(ctx, req) + results[req.GetPolicy().GetId()] = kaoResults if err != nil { continue } @@ -467,8 +499,8 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*request.RewrapReq } pdpAccessResults, accessErr := p.canAccess(ctx, tok, policies) if accessErr != nil { - failAllKaos(requests, err403("could not perform access")) - return + failAllKaos(requests, results, err403("could not perform access")) + return results } asymEncrypt, err := ocrypto.NewAsymEncryption(clientPublicKey) @@ -479,61 +511,68 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*request.RewrapReq for _, pdpAccess := range pdpAccessResults { policy := pdpAccess.Policy req, ok := policyReqs[policy] + kaoResults := results[req.GetPolicy().GetId()] if !ok { // this should not happen continue } access := pdpAccess.Access // Audit the TDF3 Rewrap - kasPolicy := request.ConvertToAuditKasPolicy(*policy) + kasPolicy := ConvertToAuditKasPolicy(*policy) - for _, kao := range req.KeyAccessObjectRequests { - policyBinding, _ := extractPolicyBinding(kao.PolicyBinding) + for _, kao := range req.GetKeyAccessObjectRequests() { + kaoRes := kaoResults[kao.GetKeyAccessObjectId()] + if kaoRes.Error != nil { + continue + } + + policyBinding, _ := extractPolicyBinding(kao.GetKeyAccessObject().GetPolicyBinding()) auditEventParams := audit.RewrapAuditEventParams{ Policy: kasPolicy, IsSuccess: access, TDFFormat: "tdf3", - Algorithm: req.Algorithm, + Algorithm: req.GetAlgorithm(), PolicyBinding: policyBinding, } if !access { p.Logger.Audit.RewrapFailure(ctx, auditEventParams) - failedKAORewrap(req.Results, kao, err403("forbidden")) + failedKAORewrap(kaoResults, kao, err403("forbidden")) continue } - rewrappedKey, err := asymEncrypt.Encrypt(kao.SymmetricKey) + rewrappedKey, err := asymEncrypt.Encrypt(kaoRes.Key) if err != nil { p.Logger.WarnContext(ctx, "rewrap: ocrypto.AsymEncryption.encrypt failed", "err", err, "clientPublicKey", clientPublicKey) p.Logger.Audit.RewrapFailure(ctx, auditEventParams) - failedKAORewrap(req.Results, kao, err400("bad key for rewrap")) + failedKAORewrap(kaoResults, kao, err400("bad key for rewrap")) continue } - req.Results.Results = append(req.Results.Results, &kaspb.KAORewrapResult{ - KeyAccessObjectId: kao.KeyAccessObjectID, - Status: kPermitStatus, - Result: &kaspb.KAORewrapResult_KasWrappedKey{KasWrappedKey: rewrappedKey}, - }) + kaoResults[kao.GetKeyAccessObjectId()] = kaoResult{ + ID: kao.GetKeyAccessObjectId(), + Key: rewrappedKey, + } - kao.Processed = true p.Logger.Audit.RewrapSuccess(ctx, auditEventParams) } } + return results } -func (p *Provider) nanoTDFRewrap(ctx context.Context, requests []*request.RewrapRequests, clientPublicKey string, entity *entityInfo) string { +func (p *Provider) nanoTDFRewrap(ctx context.Context, requests []*kaspb.RewrapRequestBody, clientPublicKey string, entity *entityInfo) (string, policyKAOResults) { + results := make(policyKAOResults) if p.Tracer != nil { var span trace.Span ctx, span = p.Tracer.Start(ctx, "rewrap-nanotdf") defer span.End() } - var policies []*request.Policy - policyReqs := make(map[*request.Policy]*request.RewrapRequests) + var policies []*Policy + policyReqs := make(map[*Policy]*kaspb.RewrapRequestBody) for _, req := range requests { - policy := p.verifyNanoRewrapRequests(ctx, req) + policy, kaoResults := p.verifyNanoRewrapRequests(ctx, req) + results[req.GetPolicy().GetId()] = kaoResults if policy != nil { policies = append(policies, policy) policyReqs[policy] = req @@ -547,20 +586,20 @@ func (p *Provider) nanoTDFRewrap(ctx context.Context, requests []*request.Rewrap pdpAccessResults, accessErr := p.canAccess(ctx, tok, policies) if accessErr != nil { - failAllKaos(requests, err403("could not perform access")) - return "" + failAllKaos(requests, results, err403("could not perform access")) + return "", results } privateKeyHandle, publicKeyHandle, err := p.CryptoProvider.GenerateEphemeralKasKeys() if err != nil { - failAllKaos(requests, fmt.Errorf("failed to generate keypair: %w", err)) - return "" + failAllKaos(requests, results, fmt.Errorf("failed to generate keypair: %w", err)) + return "", results } sessionKey, err := p.CryptoProvider.GenerateNanoTDFSessionKey(privateKeyHandle, []byte(clientPublicKey)) if err != nil { p.Logger.DebugContext(ctx, "GenerateNanoTDFSessionKey", "err", err) - failAllKaos(requests, fmt.Errorf("failed to generate session key: %w", err)) - return "" + failAllKaos(requests, results, fmt.Errorf("failed to generate session key: %w", err)) + return "", results } for _, pdpAccess := range pdpAccessResults { @@ -569,60 +608,63 @@ func (p *Provider) nanoTDFRewrap(ctx context.Context, requests []*request.Rewrap if !ok { // this should not happen continue } + kaoResults := results[req.GetPolicy().GetId()] access := pdpAccess.Access // Audit the Nano Rewrap - kasPolicy := request.ConvertToAuditKasPolicy(*policy) + kasPolicy := ConvertToAuditKasPolicy(*policy) + + for _, kao := range req.GetKeyAccessObjectRequests() { + kaoInfo := kaoResults[kao.GetKeyAccessObjectId()] + if kaoInfo.Error != nil { + continue + } - for _, kao := range req.KeyAccessObjectRequests { auditEventParams := audit.RewrapAuditEventParams{ Policy: kasPolicy, IsSuccess: access, TDFFormat: "Nano", - Algorithm: req.Algorithm, + Algorithm: req.GetAlgorithm(), } if !access { p.Logger.Audit.RewrapFailure(ctx, auditEventParams) - failedKAORewrap(req.Results, kao, err403("forbidden")) + failedKAORewrap(kaoResults, kao, err403("forbidden")) continue } - cipherText, err := wrapKeyAES(sessionKey, kao.SymmetricKey) + cipherText, err := wrapKeyAES(sessionKey, kaoInfo.Key) if err != nil { p.Logger.Audit.RewrapFailure(ctx, auditEventParams) - failedKAORewrap(req.Results, kao, err403("forbidden")) + failedKAORewrap(kaoResults, kao, err403("forbidden")) continue } - req.Results.Results = append(req.Results.Results, &kaspb.KAORewrapResult{ - KeyAccessObjectId: kao.KeyAccessObjectID, - Status: kPermitStatus, - Result: &kaspb.KAORewrapResult_KasWrappedKey{KasWrappedKey: cipherText}, - }) + kaoResults[kao.GetKeyAccessObjectId()] = kaoResult{ + ID: kao.GetKeyAccessObjectId(), + Key: cipherText, + } - kao.Processed = true p.Logger.Audit.RewrapSuccess(ctx, auditEventParams) } } - return string(publicKeyHandle) + return string(publicKeyHandle), results } -func (p *Provider) verifyNanoRewrapRequests(ctx context.Context, req *request.RewrapRequests) *request.Policy { - req.Results = &kaspb.RewrapResult{ - PolicyId: req.Policy.ID, - } - for _, kao := range req.KeyAccessObjectRequests { +func (p *Provider) verifyNanoRewrapRequests(ctx context.Context, req *kaspb.RewrapRequestBody) (*Policy, map[string]kaoResult) { + results := make(map[string]kaoResult) + + for _, kao := range req.GetKeyAccessObjectRequests() { // there should never be multiple KAOs in policy - if len(req.KeyAccessObjectRequests) != 1 { - failedKAORewrap(req.Results, kao, err400("NanoTDFs should not have multiple KAOs per Policy")) + if len(req.GetKeyAccessObjectRequests()) != 1 { + failedKAORewrap(results, kao, err400("NanoTDFs should not have multiple KAOs per Policy")) continue } - headerReader := bytes.NewReader(kao.Header) + headerReader := bytes.NewReader(kao.GetKeyAccessObject().GetHeader()) header, _, err := sdk.NewNanoTDFHeaderFromReader(headerReader) if err != nil { - failedKAORewrap(req.Results, kao, fmt.Errorf("failed to parse NanoTDF header: %w", err)) - return nil + failedKAORewrap(results, kao, fmt.Errorf("failed to parse NanoTDF header: %w", err)) + return nil, results } // Lookup KID from nano header kid, err := header.GetKasURL().GetIdentifier() @@ -632,7 +674,7 @@ func (p *Provider) verifyNanoRewrapRequests(ctx context.Context, req *request.Re kid, err = p.lookupKid(ctx, security.AlgorithmECP256R1) if err != nil { p.Logger.ErrorContext(ctx, "failure to find default kid for ec", "err", err) - failedKAORewrap(req.Results, kao, err400("bad request")) + failedKAORewrap(results, kao, err400("bad request")) continue } p.Logger.DebugContext(ctx, "nanoTDFRewrap lookupKid", "kid", kid) @@ -640,41 +682,44 @@ func (p *Provider) verifyNanoRewrapRequests(ctx context.Context, req *request.Re p.Logger.DebugContext(ctx, "nanoTDFRewrap", "kid", kid) ecCurve, err := header.ECCurve() if err != nil { - failedKAORewrap(req.Results, kao, fmt.Errorf("ECCurve failed: %w", err)) - return nil + failedKAORewrap(results, kao, fmt.Errorf("ECCurve failed: %w", err)) + return nil, results } symmetricKey, err := p.CryptoProvider.GenerateNanoTDFSymmetricKey(kid, header.EphemeralKey, ecCurve) if err != nil { - failedKAORewrap(req.Results, kao, fmt.Errorf("failed to generate symmetric key: %w", err)) - return nil + failedKAORewrap(results, kao, fmt.Errorf("failed to generate symmetric key: %w", err)) + return nil, results } // extract the policy policy, err := extractNanoPolicy(symmetricKey, header) if err != nil { - failedKAORewrap(req.Results, kao, fmt.Errorf("Error extracting policy: %w", err)) - return nil + failedKAORewrap(results, kao, fmt.Errorf("Error extracting policy: %w", err)) + return nil, results } // check the policy binding verify, err := header.VerifyPolicyBinding() if err != nil { - failedKAORewrap(req.Results, kao, fmt.Errorf("failed to verify policy binding: %w", err)) - return nil + failedKAORewrap(results, kao, fmt.Errorf("failed to verify policy binding: %w", err)) + return nil, results } if !verify { - failedKAORewrap(req.Results, kao, fmt.Errorf("policy binding verification failed")) - return nil + failedKAORewrap(results, kao, fmt.Errorf("policy binding verification failed")) + return nil, results + } + results[kao.GetKeyAccessObjectId()] = kaoResult{ + ID: kao.GetKeyAccessObjectId(), + Key: symmetricKey, } - kao.SymmetricKey = symmetricKey - return policy + return policy, results } - return nil + return nil, results } -func extractNanoPolicy(symmetricKey []byte, header sdk.NanoTDFHeader) (*request.Policy, error) { +func extractNanoPolicy(symmetricKey []byte, header sdk.NanoTDFHeader) (*Policy, error) { gcm, err := ocrypto.NewAESGcm(symmetricKey) if err != nil { return nil, fmt.Errorf("crypto.NewAESGcm:%w", err) @@ -694,7 +739,7 @@ func extractNanoPolicy(symmetricKey []byte, header sdk.NanoTDFHeader) (*request. return nil, fmt.Errorf("Error decrypting policy body:%w", err) } - var policy request.Policy + var policy Policy err = json.Unmarshal(policyData, &policy) if err != nil { return nil, fmt.Errorf("Error unmarshalling policy:%w", err) @@ -716,10 +761,10 @@ func wrapKeyAES(sessionKey, dek []byte) ([]byte, error) { return cipherText, nil } -func failAllKaos(requests []*request.RewrapRequests, err error) { - for _, req := range requests { - for _, kao := range req.KeyAccessObjectRequests { - failedKAORewrap(req.Results, kao, err) +func failAllKaos(reqs []*kaspb.RewrapRequestBody, results policyKAOResults, err error) { + for _, req := range reqs { + for _, kao := range req.GetKeyAccessObjectRequests() { + failedKAORewrap(results[req.GetPolicy().GetId()], kao, err) } } } diff --git a/service/kas/access/rewrap_test.go b/service/kas/access/rewrap_test.go index ef6cfdaab..0ec47c81d 100644 --- a/service/kas/access/rewrap_test.go +++ b/service/kas/access/rewrap_test.go @@ -8,11 +8,12 @@ import ( "encoding/hex" "encoding/json" "encoding/pem" - "errors" "log/slog" "net/http" "testing" + "google.golang.org/protobuf/encoding/protojson" + "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/lestrrat-go/jwx/v2/jws" @@ -25,7 +26,6 @@ import ( "github.com/google/uuid" kaspb "github.com/opentdf/platform/protocol/go/kas" - "github.com/opentdf/platform/service/kas/request" "google.golang.org/grpc/metadata" ) @@ -115,10 +115,10 @@ Dzq7D9lqeqSK/ds7r7hpbs4iIr6KrSuXwlXmYtnhRvKT mockIDPOrigin = "https://keycloak-http/" ) -func fauxPolicy() *request.Policy { - return &request.Policy{ +func fauxPolicy() *Policy { + return &Policy{ UUID: uuid.MustParse("12345678-1234-1234-1234-1234567890AB"), - Body: request.PolicyBody{DataAttributes: []request.Attribute{ + Body: PolicyBody{DataAttributes: []Attribute{ {URI: "https://example.com/attr/Classification/value/S"}, {URI: "https://example.com/attr/COI/value/PRX"}, }}, @@ -126,9 +126,9 @@ func fauxPolicy() *request.Policy { } func emptyPolicyBytes() []byte { - data, err := json.Marshal(request.Policy{ + data, err := json.Marshal(Policy{ UUID: uuid.MustParse("12345678-1234-1234-1234-1234567890AB"), - Body: request.PolicyBody{}, + Body: PolicyBody{}, }) if err != nil { panic(err) @@ -201,7 +201,7 @@ type PolicyBinding struct { Hash string `json:"hash"` } -func keyAccessWrappedRaw(t *testing.T, policyBindingAsString bool) request.KeyAccessObjectRequest { +func keyAccessWrappedRaw(t *testing.T, policyBindingAsString bool) kaspb.KeyAccessObjectRequest { policyBytes := fauxPolicyBytes(t) asym, err := ocrypto.NewAsymEncryption(rsaPublicAlt) require.NoError(t, err, "rewrap: NewAsymEncryption failed") @@ -225,15 +225,17 @@ func keyAccessWrappedRaw(t *testing.T, policyBindingAsString bool) request.KeyAc Hash: base64.StdEncoding.EncodeToString(dst), } } + binding, err := json.Marshal(policyBinding) + require.NoError(t, err) - return request.KeyAccessObjectRequest{ - KeyAccessObjectID: "123", - KeyAccess: request.KeyAccess{ + return kaspb.KeyAccessObjectRequest{ + KeyAccessObjectId: "123", + KeyAccessObject: &kaspb.KeyAccess{ KeyType: "wrapped", - KasURL: "http://127.0.0.1:4000", + KasUrl: "http://127.0.0.1:4000", Protocol: "kas", WrappedKey: []byte(base64.StdEncoding.EncodeToString(wrappedKey)), - PolicyBinding: policyBinding, + PolicyBinding: binding, }, } } @@ -281,13 +283,13 @@ func jwtWrongKey(t *testing.T) []byte { return signedMockJWT(t, entityPrivateKey(t)) } -func makeRewrapRequests(t *testing.T, policy []byte, bindingAsString bool) []*request.RewrapRequests { +func makeRewrapRequests(t *testing.T, policy []byte, bindingAsString bool) []*kaspb.RewrapRequestBody { kaoReq := keyAccessWrappedRaw(t, bindingAsString) - return []*request.RewrapRequests{ + return []*kaspb.RewrapRequestBody{ { - KeyAccessObjectRequests: []*request.KeyAccessObjectRequest{&kaoReq}, - Policy: request.PolicyRequest{ - ID: "123", + KeyAccessObjectRequests: []*kaspb.KeyAccessObjectRequest{&kaoReq}, + Policy: &kaspb.PolicyRequest{ + Id: "123", Body: string(policy), }, }, @@ -295,11 +297,11 @@ func makeRewrapRequests(t *testing.T, policy []byte, bindingAsString bool) []*re } func makeRewrapBody(t *testing.T, policy []byte, policyBindingAsString bool) []byte { - mockBody := request.Body{ + mockBody := &kaspb.RequestBody{ Requests: makeRewrapRequests(t, policy, policyBindingAsString), ClientPublicKey: rsaPublicAlt, } - bodyData, err := json.Marshal(mockBody) + bodyData, err := protojson.Marshal(mockBody) require.NoError(t, err) tok := jwt.New() @@ -364,14 +366,10 @@ func TestParseAndVerifyRequest(t *testing.T) { if tt.goodDPoP { require.NoError(t, err, "failed to parse srt=[%s], tok=[%s]", tt.body, bearer) require.NotNil(t, verified, "unable to load request body") - require.NotNil(t, verified.ClientPublicKey, "unable to load public key") - - for _, req := range verified.Requests { - req.Results = &kaspb.RewrapResult{} - req.KeyAccessObjectRequests[0].SymmetricKey = []byte(plainKey) + require.NotNil(t, verified.GetClientPublicKey(), "unable to load public key") - err := verifyPolicyBinding(context.Background(), []byte(req.Policy.Body), req.KeyAccessObjectRequests[0], *logger) - err = errors.Join(err, verified.Requests[0].KeyAccessObjectRequests[0].Err) + for _, req := range verified.GetRequests() { + err := verifyPolicyBinding(context.Background(), []byte(req.GetPolicy().GetBody()), req.GetKeyAccessObjectRequests()[0], []byte(plainKey), *logger) if !tt.shouldError { require.NoError(t, err, "failed to verify policy body=[%v]", tt.body) } else { diff --git a/service/kas/kas.proto b/service/kas/kas.proto index 55d832c73..cf9c69140 100644 --- a/service/kas/kas.proto +++ b/service/kas/kas.proto @@ -31,6 +31,39 @@ message LegacyPublicKeyRequest { string algorithm = 1; } +message KeyAccess { + string encrypted_metadata = 1; + bytes policy_binding = 2; + string protocol = 3; + string key_type = 4; + string kas_url = 5; + string kid = 6; + string split_id = 7; + bytes wrapped_key = 8; + bytes header = 9; + string algorithm = 10; +} +message PolicyRequest { + string id = 1; + string body = 2; +} + +message KeyAccessObjectRequest { + string key_access_object_id = 1; + KeyAccess key_access_object = 2; +} + +message RewrapRequestBody { + repeated KeyAccessObjectRequest key_access_object_requests = 1; + PolicyRequest policy = 2; + string algorithm = 3; +} + +message RequestBody { + string client_public_key = 1; + repeated RewrapRequestBody requests = 2; +} + message PublicKeyRequest { string algorithm = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "algorithm type rsa: or ec:"}]; string fmt = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "response format"}]; diff --git a/service/kas/request/rewrap.go b/service/kas/request/rewrap.go deleted file mode 100644 index 92fbdd6db..000000000 --- a/service/kas/request/rewrap.go +++ /dev/null @@ -1,36 +0,0 @@ -package request - -import "github.com/opentdf/platform/protocol/go/kas" - -const ( - PermitStatus = "permit" -) - -type PolicyRequest struct { - ID string `json:"id"` - Body string `json:"body"` -} - -type KeyAccessObjectRequest struct { - KeyAccessObjectID string `json:"keyAccessObjectId"` - KeyAccess `json:"keyAccessObject"` - - // For Platform Use - Processed bool `json:"-"` - SymmetricKey []byte `json:"-"` - Err error `json:"-"` -} - -type RewrapRequests struct { - KeyAccessObjectRequests []*KeyAccessObjectRequest `json:"keyAccessObjects"` - Policy PolicyRequest `json:"policy"` - Algorithm string `json:"algorithm,omitempty"` - - // For Platform Use - Results *kas.RewrapResult `json:"-"` -} - -type Body struct { - Requests []*RewrapRequests `json:"requests"` - ClientPublicKey string `json:"clientPublicKey"` -} diff --git a/service/rttests/rt_test.go b/service/rttests/rt_test.go index 624f443a8..ba8004a6c 100644 --- a/service/rttests/rt_test.go +++ b/service/rttests/rt_test.go @@ -413,7 +413,11 @@ func bulk(client *sdk.SDK, tdfSuccess []string, tdfFail []string, plaintext stri req.TDFType = sdk.Standard _ = client.BulkDecrypt(context.Background(), req) for _, tdf := range passTDF { - builder := tdf.Writer.(*strings.Builder) + builder, ok := tdf.Writer.(*strings.Builder) + if !ok { + return fmt.Errorf("bad writer") + } + if tdf.Error != nil { return tdf.Error }