diff --git a/docs/grpc/index.html b/docs/grpc/index.html index e83c36c17a..f4b3ab3218 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -866,6 +866,10 @@

Table of Contents

MActivatePublicKeyResponse +
  • + MChangeMappings +
  • +
  • MCreateKeyAccessServerRequest
  • @@ -1006,6 +1010,10 @@

    Table of Contents

    MRotateKeyResponse +
  • + MRotatedResources +
  • +
  • MUpdateKeyAccessServerRequest
  • @@ -7463,6 +7471,37 @@

    ActivatePublicKeyResponse< +

    ChangeMappings

    +

    Simplified information about the resources that were rotated as part of the key rotation process.

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

    fqnstring

    + + + + +

    CreateKeyAccessServerRequest

    @@ -8720,31 +8759,29 @@

    RotateKeyRequest.NewKey

    - private_key_ctx + public_key_ctx bytes -

    Required - -Specific structure based on key provider implementation

    +

    Required

    - public_key_ctx + private_key_ctx bytes -

    Optional

    +

    Specific structure based on key provider implementation

    provider_config_id string -

    +

    Optional

    metadata - common.Metadata + common.MetadataMutable

    Common metadata fields

    @@ -8773,6 +8810,58 @@

    RotateKeyResponse

    The newly rotated Kas Key

    + + rotated_resources + RotatedResources + +

    All resources that were rotated as part of the key rotation process

    + + + + + + + + + +

    RotatedResources

    +

    All resources that were rotated as part of the key rotation process

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    rotated_out_keypolicy.KasKey

    The old key that was rotated out

    attribute_definition_mappingsChangeMappingsrepeated

    attribute_value_mappingsChangeMappingsrepeated

    namespace_mappingsChangeMappingsrepeated

    diff --git a/docs/openapi/policy/kasregistry/key_access_server_registry.swagger.json b/docs/openapi/policy/kasregistry/key_access_server_registry.swagger.json index 7717af9d28..00d34895f3 100644 --- a/docs/openapi/policy/kasregistry/key_access_server_registry.swagger.json +++ b/docs/openapi/policy/kasregistry/key_access_server_registry.swagger.json @@ -306,22 +306,22 @@ "$ref": "#/definitions/policyKeyMode", "title": "Required" }, - "privateKeyCtx": { + "publicKeyCtx": { "type": "string", "format": "byte", - "description": "Specific structure based on key provider implementation", "title": "Required" }, - "publicKeyCtx": { + "privateKeyCtx": { "type": "string", "format": "byte", - "title": "Optional" + "title": "Specific structure based on key provider implementation" }, "providerConfigId": { - "type": "string" + "type": "string", + "title": "Optional" }, "metadata": { - "$ref": "#/definitions/commonMetadata", + "$ref": "#/definitions/commonMetadataMutable", "title": "Common metadata fields" } }, @@ -372,6 +372,18 @@ "default": "METADATA_UPDATE_ENUM_UNSPECIFIED", "title": "- METADATA_UPDATE_ENUM_UNSPECIFIED: unspecified update type\n - METADATA_UPDATE_ENUM_EXTEND: only update the fields that are provided\n - METADATA_UPDATE_ENUM_REPLACE: replace the entire metadata with the provided metadata" }, + "kasregistryChangeMappings": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "fqn": { + "type": "string" + } + }, + "description": "*\nSimplified information about the resources that were rotated as part of the key rotation process." + }, "kasregistryCreateKeyAccessServerRequest": { "type": "object", "properties": { @@ -557,10 +569,45 @@ "kasKey": { "$ref": "#/definitions/policyKasKey", "title": "The newly rotated Kas Key" + }, + "rotatedResources": { + "$ref": "#/definitions/kasregistryRotatedResources", + "title": "All resources that were rotated as part of the key rotation process" } }, "title": "Response message for the RotateKey request" }, + "kasregistryRotatedResources": { + "type": "object", + "properties": { + "rotatedOutKey": { + "$ref": "#/definitions/policyKasKey", + "title": "The old key that was rotated out" + }, + "attributeDefinitionMappings": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/kasregistryChangeMappings" + } + }, + "attributeValueMappings": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/kasregistryChangeMappings" + } + }, + "namespaceMappings": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/kasregistryChangeMappings" + } + } + }, + "title": "All resources that were rotated as part of the key rotation process" + }, "kasregistryUpdateKeyAccessServerResponse": { "type": "object", "properties": { diff --git a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go index bde5eccdea..99cfdd1e1b 100644 --- a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go +++ b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go @@ -2581,6 +2581,135 @@ func (*RotateKeyRequest_Id) isRotateKeyRequest_ActiveKey() {} func (*RotateKeyRequest_Key) isRotateKeyRequest_ActiveKey() {} +// * +// Simplified information about the resources that were rotated as part of the key rotation process. +type ChangeMappings struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Fqn string `protobuf:"bytes,2,opt,name=fqn,proto3" json:"fqn,omitempty"` +} + +func (x *ChangeMappings) Reset() { + *x = ChangeMappings{} + if protoimpl.UnsafeEnabled { + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChangeMappings) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChangeMappings) ProtoMessage() {} + +func (x *ChangeMappings) ProtoReflect() protoreflect.Message { + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[38] + 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 ChangeMappings.ProtoReflect.Descriptor instead. +func (*ChangeMappings) Descriptor() ([]byte, []int) { + return file_policy_kasregistry_key_access_server_registry_proto_rawDescGZIP(), []int{38} +} + +func (x *ChangeMappings) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ChangeMappings) GetFqn() string { + if x != nil { + return x.Fqn + } + return "" +} + +// All resources that were rotated as part of the key rotation process +type RotatedResources struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RotatedOutKey *policy.KasKey `protobuf:"bytes,1,opt,name=rotated_out_key,json=rotatedOutKey,proto3" json:"rotated_out_key,omitempty"` // The old key that was rotated out + AttributeDefinitionMappings []*ChangeMappings `protobuf:"bytes,2,rep,name=attribute_definition_mappings,json=attributeDefinitionMappings,proto3" json:"attribute_definition_mappings,omitempty"` + AttributeValueMappings []*ChangeMappings `protobuf:"bytes,3,rep,name=attribute_value_mappings,json=attributeValueMappings,proto3" json:"attribute_value_mappings,omitempty"` + NamespaceMappings []*ChangeMappings `protobuf:"bytes,4,rep,name=namespace_mappings,json=namespaceMappings,proto3" json:"namespace_mappings,omitempty"` +} + +func (x *RotatedResources) Reset() { + *x = RotatedResources{} + if protoimpl.UnsafeEnabled { + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RotatedResources) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RotatedResources) ProtoMessage() {} + +func (x *RotatedResources) ProtoReflect() protoreflect.Message { + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[39] + 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 RotatedResources.ProtoReflect.Descriptor instead. +func (*RotatedResources) Descriptor() ([]byte, []int) { + return file_policy_kasregistry_key_access_server_registry_proto_rawDescGZIP(), []int{39} +} + +func (x *RotatedResources) GetRotatedOutKey() *policy.KasKey { + if x != nil { + return x.RotatedOutKey + } + return nil +} + +func (x *RotatedResources) GetAttributeDefinitionMappings() []*ChangeMappings { + if x != nil { + return x.AttributeDefinitionMappings + } + return nil +} + +func (x *RotatedResources) GetAttributeValueMappings() []*ChangeMappings { + if x != nil { + return x.AttributeValueMappings + } + return nil +} + +func (x *RotatedResources) GetNamespaceMappings() []*ChangeMappings { + if x != nil { + return x.NamespaceMappings + } + return nil +} + // Response message for the RotateKey request type RotateKeyResponse struct { state protoimpl.MessageState @@ -2589,12 +2718,14 @@ type RotateKeyResponse struct { // The newly rotated Kas Key KasKey *policy.KasKey `protobuf:"bytes,1,opt,name=kas_key,json=kasKey,proto3" json:"kas_key,omitempty"` + // All resources that were rotated as part of the key rotation process + RotatedResources *RotatedResources `protobuf:"bytes,2,opt,name=rotated_resources,json=rotatedResources,proto3" json:"rotated_resources,omitempty"` } func (x *RotateKeyResponse) Reset() { *x = RotateKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[38] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2607,7 +2738,7 @@ func (x *RotateKeyResponse) String() string { func (*RotateKeyResponse) ProtoMessage() {} func (x *RotateKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[38] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2620,7 +2751,7 @@ func (x *RotateKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RotateKeyResponse.ProtoReflect.Descriptor instead. func (*RotateKeyResponse) Descriptor() ([]byte, []int) { - return file_policy_kasregistry_key_access_server_registry_proto_rawDescGZIP(), []int{38} + return file_policy_kasregistry_key_access_server_registry_proto_rawDescGZIP(), []int{40} } func (x *RotateKeyResponse) GetKasKey() *policy.KasKey { @@ -2630,6 +2761,13 @@ func (x *RotateKeyResponse) GetKasKey() *policy.KasKey { return nil } +func (x *RotateKeyResponse) GetRotatedResources() *RotatedResources { + if x != nil { + return x.RotatedResources + } + return nil +} + type ListPublicKeyMappingResponse_PublicKeyMapping struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2644,7 +2782,7 @@ type ListPublicKeyMappingResponse_PublicKeyMapping struct { func (x *ListPublicKeyMappingResponse_PublicKeyMapping) Reset() { *x = ListPublicKeyMappingResponse_PublicKeyMapping{} if protoimpl.UnsafeEnabled { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[39] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2657,7 +2795,7 @@ func (x *ListPublicKeyMappingResponse_PublicKeyMapping) String() string { func (*ListPublicKeyMappingResponse_PublicKeyMapping) ProtoMessage() {} func (x *ListPublicKeyMappingResponse_PublicKeyMapping) ProtoReflect() protoreflect.Message { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[39] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2715,7 +2853,7 @@ type ListPublicKeyMappingResponse_PublicKey struct { func (x *ListPublicKeyMappingResponse_PublicKey) Reset() { *x = ListPublicKeyMappingResponse_PublicKey{} if protoimpl.UnsafeEnabled { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[40] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2728,7 +2866,7 @@ func (x *ListPublicKeyMappingResponse_PublicKey) String() string { func (*ListPublicKeyMappingResponse_PublicKey) ProtoMessage() {} func (x *ListPublicKeyMappingResponse_PublicKey) ProtoReflect() protoreflect.Message { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[40] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2784,7 +2922,7 @@ type ListPublicKeyMappingResponse_Association struct { func (x *ListPublicKeyMappingResponse_Association) Reset() { *x = ListPublicKeyMappingResponse_Association{} if protoimpl.UnsafeEnabled { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[41] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2797,7 +2935,7 @@ func (x *ListPublicKeyMappingResponse_Association) String() string { func (*ListPublicKeyMappingResponse_Association) ProtoMessage() {} func (x *ListPublicKeyMappingResponse_Association) ProtoReflect() protoreflect.Message { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[41] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2840,18 +2978,18 @@ type RotateKeyRequest_NewKey struct { // Required KeyMode policy.KeyMode `protobuf:"varint,3,opt,name=key_mode,json=keyMode,proto3,enum=policy.KeyMode" json:"key_mode,omitempty"` // Required - PrivateKeyCtx []byte `protobuf:"bytes,4,opt,name=private_key_ctx,json=privateKeyCtx,proto3" json:"private_key_ctx,omitempty"` // Specific structure based on key provider implementation + PublicKeyCtx []byte `protobuf:"bytes,4,opt,name=public_key_ctx,json=publicKeyCtx,proto3" json:"public_key_ctx,omitempty"` + PrivateKeyCtx []byte `protobuf:"bytes,5,opt,name=private_key_ctx,json=privateKeyCtx,proto3" json:"private_key_ctx,omitempty"` // Specific structure based on key provider implementation // Optional - PublicKeyCtx []byte `protobuf:"bytes,5,opt,name=public_key_ctx,json=publicKeyCtx,proto3" json:"public_key_ctx,omitempty"` ProviderConfigId string `protobuf:"bytes,6,opt,name=provider_config_id,json=providerConfigId,proto3" json:"provider_config_id,omitempty"` // Common metadata fields - Metadata *common.Metadata `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` + Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` } func (x *RotateKeyRequest_NewKey) Reset() { *x = RotateKeyRequest_NewKey{} if protoimpl.UnsafeEnabled { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[42] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2864,7 +3002,7 @@ func (x *RotateKeyRequest_NewKey) String() string { func (*RotateKeyRequest_NewKey) ProtoMessage() {} func (x *RotateKeyRequest_NewKey) ProtoReflect() protoreflect.Message { - mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[42] + mi := &file_policy_kasregistry_key_access_server_registry_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2901,16 +3039,16 @@ func (x *RotateKeyRequest_NewKey) GetKeyMode() policy.KeyMode { return policy.KeyMode(0) } -func (x *RotateKeyRequest_NewKey) GetPrivateKeyCtx() []byte { +func (x *RotateKeyRequest_NewKey) GetPublicKeyCtx() []byte { if x != nil { - return x.PrivateKeyCtx + return x.PublicKeyCtx } return nil } -func (x *RotateKeyRequest_NewKey) GetPublicKeyCtx() []byte { +func (x *RotateKeyRequest_NewKey) GetPrivateKeyCtx() []byte { if x != nil { - return x.PublicKeyCtx + return x.PrivateKeyCtx } return nil } @@ -2922,7 +3060,7 @@ func (x *RotateKeyRequest_NewKey) GetProviderConfigId() string { return "" } -func (x *RotateKeyRequest_NewKey) GetMetadata() *common.Metadata { +func (x *RotateKeyRequest_NewKey) GetMetadata() *common.MetadataMutable { if x != nil { return x.Metadata } @@ -3447,7 +3585,7 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x00, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x19, 0x0a, 0x03, 0x6b, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, - 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x82, 0x04, 0x0a, 0x10, 0x52, 0x6f, 0x74, 0x61, 0x74, + 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x99, 0x04, 0x0a, 0x10, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, @@ -3458,7 +3596,7 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x52, - 0x06, 0x6e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x1a, 0xc3, 0x02, 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x4b, + 0x06, 0x6e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x1a, 0xd3, 0x02, 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, @@ -3468,127 +3606,160 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x42, 0x08, 0xba, 0x48, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78, 0x12, 0x24, 0x0a, 0x0e, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x43, 0x74, - 0x78, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x12, - 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x0c, 0x0a, - 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x3c, 0x0a, 0x11, 0x52, - 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x27, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, - 0x79, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x32, 0xad, 0x0b, 0x0a, 0x1e, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x99, 0x01, 0x0a, - 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, - 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x12, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x90, 0x02, 0x01, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, - 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x90, 0x02, 0x01, 0x12, 0x9c, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, + 0x6f, 0x64, 0x65, 0x12, 0x2d, 0x0a, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x7a, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x43, + 0x74, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, + 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x70, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x13, 0x0a, + 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x05, 0xba, 0x48, 0x02, + 0x08, 0x01, 0x22, 0x32, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x22, 0xe3, 0x02, 0x0a, 0x10, 0x52, 0x6f, 0x74, 0x61, 0x74, + 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0f, 0x72, + 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, + 0x73, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, + 0x4b, 0x65, 0x79, 0x12, 0x66, 0x0a, 0x1d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x1b, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5c, 0x0a, 0x18, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, - 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, 0x2f, 0x6b, - 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, - 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaf, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, - 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, - 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, - 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, + 0x72, 0x79, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x16, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x51, 0x0a, 0x12, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, + 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x11, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x8f, 0x01, 0x0a, + 0x11, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, + 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x51, 0x0a, 0x11, 0x72, + 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61, + 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x10, 0x72, 0x6f, + 0x74, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x32, 0xad, + 0x0b, 0x0a, 0x1e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x99, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, 0x65, 0x79, - 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, - 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x90, 0x02, 0x01, 0x12, 0x5a, 0x0a, 0x09, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, - 0x21, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, - 0x4b, 0x65, 0x79, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, - 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, - 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x90, 0x02, 0x01, 0x12, 0x98, 0x01, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, + 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, + 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, + 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x90, 0x02, 0x01, 0x12, 0x9c, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, + 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, + 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, + 0x2a, 0x32, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x15, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, + 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaf, 0x01, 0x0a, + 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, + 0x1a, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x90, 0x02, 0x01, 0x12, 0x5a, + 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x06, 0x47, 0x65, + 0x74, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, + 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, + 0x08, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x5a, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x24, + 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, - 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, - 0x09, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, - 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, - 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, - 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x09, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, + 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, + 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xdb, + 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, + 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, + 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0xca, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, + 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, + 0x3a, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3603,7 +3774,7 @@ func file_policy_kasregistry_key_access_server_registry_proto_rawDescGZIP() []by return file_policy_kasregistry_key_access_server_registry_proto_rawDescData } -var file_policy_kasregistry_key_access_server_registry_proto_msgTypes = make([]protoimpl.MessageInfo, 43) +var file_policy_kasregistry_key_access_server_registry_proto_msgTypes = make([]protoimpl.MessageInfo, 45) var file_policy_kasregistry_key_access_server_registry_proto_goTypes = []interface{}{ (*GetKeyAccessServerRequest)(nil), // 0: policy.kasregistry.GetKeyAccessServerRequest (*GetKeyAccessServerResponse)(nil), // 1: policy.kasregistry.GetKeyAccessServerResponse @@ -3643,115 +3814,121 @@ var file_policy_kasregistry_key_access_server_registry_proto_goTypes = []interfa (*UpdateKeyResponse)(nil), // 35: policy.kasregistry.UpdateKeyResponse (*KasKeyIdentifier)(nil), // 36: policy.kasregistry.KasKeyIdentifier (*RotateKeyRequest)(nil), // 37: policy.kasregistry.RotateKeyRequest - (*RotateKeyResponse)(nil), // 38: policy.kasregistry.RotateKeyResponse - (*ListPublicKeyMappingResponse_PublicKeyMapping)(nil), // 39: policy.kasregistry.ListPublicKeyMappingResponse.PublicKeyMapping - (*ListPublicKeyMappingResponse_PublicKey)(nil), // 40: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey - (*ListPublicKeyMappingResponse_Association)(nil), // 41: policy.kasregistry.ListPublicKeyMappingResponse.Association - (*RotateKeyRequest_NewKey)(nil), // 42: policy.kasregistry.RotateKeyRequest.NewKey - (*policy.KeyAccessServer)(nil), // 43: policy.KeyAccessServer - (*policy.PageRequest)(nil), // 44: policy.PageRequest - (*policy.PageResponse)(nil), // 45: policy.PageResponse - (*policy.PublicKey)(nil), // 46: policy.PublicKey - (policy.SourceType)(0), // 47: policy.SourceType - (*common.MetadataMutable)(nil), // 48: common.MetadataMutable - (common.MetadataUpdateEnum)(0), // 49: common.MetadataUpdateEnum - (*policy.KasPublicKey)(nil), // 50: policy.KasPublicKey - (*policy.Key)(nil), // 51: policy.Key - (policy.Algorithm)(0), // 52: policy.Algorithm - (policy.KeyMode)(0), // 53: policy.KeyMode - (*policy.KasKey)(nil), // 54: policy.KasKey - (policy.KeyStatus)(0), // 55: policy.KeyStatus - (*common.Metadata)(nil), // 56: common.Metadata + (*ChangeMappings)(nil), // 38: policy.kasregistry.ChangeMappings + (*RotatedResources)(nil), // 39: policy.kasregistry.RotatedResources + (*RotateKeyResponse)(nil), // 40: policy.kasregistry.RotateKeyResponse + (*ListPublicKeyMappingResponse_PublicKeyMapping)(nil), // 41: policy.kasregistry.ListPublicKeyMappingResponse.PublicKeyMapping + (*ListPublicKeyMappingResponse_PublicKey)(nil), // 42: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey + (*ListPublicKeyMappingResponse_Association)(nil), // 43: policy.kasregistry.ListPublicKeyMappingResponse.Association + (*RotateKeyRequest_NewKey)(nil), // 44: policy.kasregistry.RotateKeyRequest.NewKey + (*policy.KeyAccessServer)(nil), // 45: policy.KeyAccessServer + (*policy.PageRequest)(nil), // 46: policy.PageRequest + (*policy.PageResponse)(nil), // 47: policy.PageResponse + (*policy.PublicKey)(nil), // 48: policy.PublicKey + (policy.SourceType)(0), // 49: policy.SourceType + (*common.MetadataMutable)(nil), // 50: common.MetadataMutable + (common.MetadataUpdateEnum)(0), // 51: common.MetadataUpdateEnum + (*policy.KasPublicKey)(nil), // 52: policy.KasPublicKey + (*policy.Key)(nil), // 53: policy.Key + (policy.Algorithm)(0), // 54: policy.Algorithm + (policy.KeyMode)(0), // 55: policy.KeyMode + (*policy.KasKey)(nil), // 56: policy.KasKey + (policy.KeyStatus)(0), // 57: policy.KeyStatus } var file_policy_kasregistry_key_access_server_registry_proto_depIdxs = []int32{ - 43, // 0: policy.kasregistry.GetKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer - 44, // 1: policy.kasregistry.ListKeyAccessServersRequest.pagination:type_name -> policy.PageRequest - 43, // 2: policy.kasregistry.ListKeyAccessServersResponse.key_access_servers:type_name -> policy.KeyAccessServer - 45, // 3: policy.kasregistry.ListKeyAccessServersResponse.pagination:type_name -> policy.PageResponse - 46, // 4: policy.kasregistry.CreateKeyAccessServerRequest.public_key:type_name -> policy.PublicKey - 47, // 5: policy.kasregistry.CreateKeyAccessServerRequest.source_type:type_name -> policy.SourceType - 48, // 6: policy.kasregistry.CreateKeyAccessServerRequest.metadata:type_name -> common.MetadataMutable - 43, // 7: policy.kasregistry.CreateKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer - 46, // 8: policy.kasregistry.UpdateKeyAccessServerRequest.public_key:type_name -> policy.PublicKey - 47, // 9: policy.kasregistry.UpdateKeyAccessServerRequest.source_type:type_name -> policy.SourceType - 48, // 10: policy.kasregistry.UpdateKeyAccessServerRequest.metadata:type_name -> common.MetadataMutable - 49, // 11: policy.kasregistry.UpdateKeyAccessServerRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 43, // 12: policy.kasregistry.UpdateKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer - 43, // 13: policy.kasregistry.DeleteKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer - 43, // 14: policy.kasregistry.KeyAccessServerGrants.key_access_server:type_name -> policy.KeyAccessServer + 45, // 0: policy.kasregistry.GetKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer + 46, // 1: policy.kasregistry.ListKeyAccessServersRequest.pagination:type_name -> policy.PageRequest + 45, // 2: policy.kasregistry.ListKeyAccessServersResponse.key_access_servers:type_name -> policy.KeyAccessServer + 47, // 3: policy.kasregistry.ListKeyAccessServersResponse.pagination:type_name -> policy.PageResponse + 48, // 4: policy.kasregistry.CreateKeyAccessServerRequest.public_key:type_name -> policy.PublicKey + 49, // 5: policy.kasregistry.CreateKeyAccessServerRequest.source_type:type_name -> policy.SourceType + 50, // 6: policy.kasregistry.CreateKeyAccessServerRequest.metadata:type_name -> common.MetadataMutable + 45, // 7: policy.kasregistry.CreateKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer + 48, // 8: policy.kasregistry.UpdateKeyAccessServerRequest.public_key:type_name -> policy.PublicKey + 49, // 9: policy.kasregistry.UpdateKeyAccessServerRequest.source_type:type_name -> policy.SourceType + 50, // 10: policy.kasregistry.UpdateKeyAccessServerRequest.metadata:type_name -> common.MetadataMutable + 51, // 11: policy.kasregistry.UpdateKeyAccessServerRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 45, // 12: policy.kasregistry.UpdateKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer + 45, // 13: policy.kasregistry.DeleteKeyAccessServerResponse.key_access_server:type_name -> policy.KeyAccessServer + 45, // 14: policy.kasregistry.KeyAccessServerGrants.key_access_server:type_name -> policy.KeyAccessServer 10, // 15: policy.kasregistry.KeyAccessServerGrants.namespace_grants:type_name -> policy.kasregistry.GrantedPolicyObject 10, // 16: policy.kasregistry.KeyAccessServerGrants.attribute_grants:type_name -> policy.kasregistry.GrantedPolicyObject 10, // 17: policy.kasregistry.KeyAccessServerGrants.value_grants:type_name -> policy.kasregistry.GrantedPolicyObject - 50, // 18: policy.kasregistry.CreatePublicKeyRequest.key:type_name -> policy.KasPublicKey - 48, // 19: policy.kasregistry.CreatePublicKeyRequest.metadata:type_name -> common.MetadataMutable - 51, // 20: policy.kasregistry.CreatePublicKeyResponse.key:type_name -> policy.Key - 51, // 21: policy.kasregistry.GetPublicKeyResponse.key:type_name -> policy.Key - 44, // 22: policy.kasregistry.ListPublicKeysRequest.pagination:type_name -> policy.PageRequest - 51, // 23: policy.kasregistry.ListPublicKeysResponse.keys:type_name -> policy.Key - 45, // 24: policy.kasregistry.ListPublicKeysResponse.pagination:type_name -> policy.PageResponse - 44, // 25: policy.kasregistry.ListPublicKeyMappingRequest.pagination:type_name -> policy.PageRequest - 39, // 26: policy.kasregistry.ListPublicKeyMappingResponse.public_key_mappings:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.PublicKeyMapping - 45, // 27: policy.kasregistry.ListPublicKeyMappingResponse.pagination:type_name -> policy.PageResponse - 48, // 28: policy.kasregistry.UpdatePublicKeyRequest.metadata:type_name -> common.MetadataMutable - 49, // 29: policy.kasregistry.UpdatePublicKeyRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 51, // 30: policy.kasregistry.UpdatePublicKeyResponse.key:type_name -> policy.Key - 51, // 31: policy.kasregistry.DeactivatePublicKeyResponse.key:type_name -> policy.Key - 51, // 32: policy.kasregistry.ActivatePublicKeyResponse.key:type_name -> policy.Key - 44, // 33: policy.kasregistry.ListKeyAccessServerGrantsRequest.pagination:type_name -> policy.PageRequest + 52, // 18: policy.kasregistry.CreatePublicKeyRequest.key:type_name -> policy.KasPublicKey + 50, // 19: policy.kasregistry.CreatePublicKeyRequest.metadata:type_name -> common.MetadataMutable + 53, // 20: policy.kasregistry.CreatePublicKeyResponse.key:type_name -> policy.Key + 53, // 21: policy.kasregistry.GetPublicKeyResponse.key:type_name -> policy.Key + 46, // 22: policy.kasregistry.ListPublicKeysRequest.pagination:type_name -> policy.PageRequest + 53, // 23: policy.kasregistry.ListPublicKeysResponse.keys:type_name -> policy.Key + 47, // 24: policy.kasregistry.ListPublicKeysResponse.pagination:type_name -> policy.PageResponse + 46, // 25: policy.kasregistry.ListPublicKeyMappingRequest.pagination:type_name -> policy.PageRequest + 41, // 26: policy.kasregistry.ListPublicKeyMappingResponse.public_key_mappings:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.PublicKeyMapping + 47, // 27: policy.kasregistry.ListPublicKeyMappingResponse.pagination:type_name -> policy.PageResponse + 50, // 28: policy.kasregistry.UpdatePublicKeyRequest.metadata:type_name -> common.MetadataMutable + 51, // 29: policy.kasregistry.UpdatePublicKeyRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 53, // 30: policy.kasregistry.UpdatePublicKeyResponse.key:type_name -> policy.Key + 53, // 31: policy.kasregistry.DeactivatePublicKeyResponse.key:type_name -> policy.Key + 53, // 32: policy.kasregistry.ActivatePublicKeyResponse.key:type_name -> policy.Key + 46, // 33: policy.kasregistry.ListKeyAccessServerGrantsRequest.pagination:type_name -> policy.PageRequest 11, // 34: policy.kasregistry.ListKeyAccessServerGrantsResponse.grants:type_name -> policy.kasregistry.KeyAccessServerGrants - 45, // 35: policy.kasregistry.ListKeyAccessServerGrantsResponse.pagination:type_name -> policy.PageResponse - 52, // 36: policy.kasregistry.CreateKeyRequest.key_algorithm:type_name -> policy.Algorithm - 53, // 37: policy.kasregistry.CreateKeyRequest.key_mode:type_name -> policy.KeyMode - 48, // 38: policy.kasregistry.CreateKeyRequest.metadata:type_name -> common.MetadataMutable - 54, // 39: policy.kasregistry.CreateKeyResponse.kas_key:type_name -> policy.KasKey + 47, // 35: policy.kasregistry.ListKeyAccessServerGrantsResponse.pagination:type_name -> policy.PageResponse + 54, // 36: policy.kasregistry.CreateKeyRequest.key_algorithm:type_name -> policy.Algorithm + 55, // 37: policy.kasregistry.CreateKeyRequest.key_mode:type_name -> policy.KeyMode + 50, // 38: policy.kasregistry.CreateKeyRequest.metadata:type_name -> common.MetadataMutable + 56, // 39: policy.kasregistry.CreateKeyResponse.kas_key:type_name -> policy.KasKey 36, // 40: policy.kasregistry.GetKeyRequest.key:type_name -> policy.kasregistry.KasKeyIdentifier - 54, // 41: policy.kasregistry.GetKeyResponse.kas_key:type_name -> policy.KasKey - 52, // 42: policy.kasregistry.ListKeysRequest.key_algorithm:type_name -> policy.Algorithm - 44, // 43: policy.kasregistry.ListKeysRequest.pagination:type_name -> policy.PageRequest - 54, // 44: policy.kasregistry.ListKeysResponse.kas_keys:type_name -> policy.KasKey - 45, // 45: policy.kasregistry.ListKeysResponse.pagination:type_name -> policy.PageResponse - 55, // 46: policy.kasregistry.UpdateKeyRequest.key_status:type_name -> policy.KeyStatus - 48, // 47: policy.kasregistry.UpdateKeyRequest.metadata:type_name -> common.MetadataMutable - 49, // 48: policy.kasregistry.UpdateKeyRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 54, // 49: policy.kasregistry.UpdateKeyResponse.kas_key:type_name -> policy.KasKey + 56, // 41: policy.kasregistry.GetKeyResponse.kas_key:type_name -> policy.KasKey + 54, // 42: policy.kasregistry.ListKeysRequest.key_algorithm:type_name -> policy.Algorithm + 46, // 43: policy.kasregistry.ListKeysRequest.pagination:type_name -> policy.PageRequest + 56, // 44: policy.kasregistry.ListKeysResponse.kas_keys:type_name -> policy.KasKey + 47, // 45: policy.kasregistry.ListKeysResponse.pagination:type_name -> policy.PageResponse + 57, // 46: policy.kasregistry.UpdateKeyRequest.key_status:type_name -> policy.KeyStatus + 50, // 47: policy.kasregistry.UpdateKeyRequest.metadata:type_name -> common.MetadataMutable + 51, // 48: policy.kasregistry.UpdateKeyRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 56, // 49: policy.kasregistry.UpdateKeyResponse.kas_key:type_name -> policy.KasKey 36, // 50: policy.kasregistry.RotateKeyRequest.key:type_name -> policy.kasregistry.KasKeyIdentifier - 42, // 51: policy.kasregistry.RotateKeyRequest.new_key:type_name -> policy.kasregistry.RotateKeyRequest.NewKey - 54, // 52: policy.kasregistry.RotateKeyResponse.kas_key:type_name -> policy.KasKey - 40, // 53: policy.kasregistry.ListPublicKeyMappingResponse.PublicKeyMapping.public_keys:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.PublicKey - 51, // 54: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.key:type_name -> policy.Key - 41, // 55: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.values:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.Association - 41, // 56: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.definitions:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.Association - 41, // 57: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.namespaces:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.Association - 52, // 58: policy.kasregistry.RotateKeyRequest.NewKey.algorithm:type_name -> policy.Algorithm - 53, // 59: policy.kasregistry.RotateKeyRequest.NewKey.key_mode:type_name -> policy.KeyMode - 56, // 60: policy.kasregistry.RotateKeyRequest.NewKey.metadata:type_name -> common.Metadata - 2, // 61: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServers:input_type -> policy.kasregistry.ListKeyAccessServersRequest - 0, // 62: policy.kasregistry.KeyAccessServerRegistryService.GetKeyAccessServer:input_type -> policy.kasregistry.GetKeyAccessServerRequest - 4, // 63: policy.kasregistry.KeyAccessServerRegistryService.CreateKeyAccessServer:input_type -> policy.kasregistry.CreateKeyAccessServerRequest - 6, // 64: policy.kasregistry.KeyAccessServerRegistryService.UpdateKeyAccessServer:input_type -> policy.kasregistry.UpdateKeyAccessServerRequest - 8, // 65: policy.kasregistry.KeyAccessServerRegistryService.DeleteKeyAccessServer:input_type -> policy.kasregistry.DeleteKeyAccessServerRequest - 26, // 66: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServerGrants:input_type -> policy.kasregistry.ListKeyAccessServerGrantsRequest - 28, // 67: policy.kasregistry.KeyAccessServerRegistryService.CreateKey:input_type -> policy.kasregistry.CreateKeyRequest - 30, // 68: policy.kasregistry.KeyAccessServerRegistryService.GetKey:input_type -> policy.kasregistry.GetKeyRequest - 32, // 69: policy.kasregistry.KeyAccessServerRegistryService.ListKeys:input_type -> policy.kasregistry.ListKeysRequest - 34, // 70: policy.kasregistry.KeyAccessServerRegistryService.UpdateKey:input_type -> policy.kasregistry.UpdateKeyRequest - 37, // 71: policy.kasregistry.KeyAccessServerRegistryService.RotateKey:input_type -> policy.kasregistry.RotateKeyRequest - 3, // 72: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServers:output_type -> policy.kasregistry.ListKeyAccessServersResponse - 1, // 73: policy.kasregistry.KeyAccessServerRegistryService.GetKeyAccessServer:output_type -> policy.kasregistry.GetKeyAccessServerResponse - 5, // 74: policy.kasregistry.KeyAccessServerRegistryService.CreateKeyAccessServer:output_type -> policy.kasregistry.CreateKeyAccessServerResponse - 7, // 75: policy.kasregistry.KeyAccessServerRegistryService.UpdateKeyAccessServer:output_type -> policy.kasregistry.UpdateKeyAccessServerResponse - 9, // 76: policy.kasregistry.KeyAccessServerRegistryService.DeleteKeyAccessServer:output_type -> policy.kasregistry.DeleteKeyAccessServerResponse - 27, // 77: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServerGrants:output_type -> policy.kasregistry.ListKeyAccessServerGrantsResponse - 29, // 78: policy.kasregistry.KeyAccessServerRegistryService.CreateKey:output_type -> policy.kasregistry.CreateKeyResponse - 31, // 79: policy.kasregistry.KeyAccessServerRegistryService.GetKey:output_type -> policy.kasregistry.GetKeyResponse - 33, // 80: policy.kasregistry.KeyAccessServerRegistryService.ListKeys:output_type -> policy.kasregistry.ListKeysResponse - 35, // 81: policy.kasregistry.KeyAccessServerRegistryService.UpdateKey:output_type -> policy.kasregistry.UpdateKeyResponse - 38, // 82: policy.kasregistry.KeyAccessServerRegistryService.RotateKey:output_type -> policy.kasregistry.RotateKeyResponse - 72, // [72:83] is the sub-list for method output_type - 61, // [61:72] is the sub-list for method input_type - 61, // [61:61] is the sub-list for extension type_name - 61, // [61:61] is the sub-list for extension extendee - 0, // [0:61] is the sub-list for field type_name + 44, // 51: policy.kasregistry.RotateKeyRequest.new_key:type_name -> policy.kasregistry.RotateKeyRequest.NewKey + 56, // 52: policy.kasregistry.RotatedResources.rotated_out_key:type_name -> policy.KasKey + 38, // 53: policy.kasregistry.RotatedResources.attribute_definition_mappings:type_name -> policy.kasregistry.ChangeMappings + 38, // 54: policy.kasregistry.RotatedResources.attribute_value_mappings:type_name -> policy.kasregistry.ChangeMappings + 38, // 55: policy.kasregistry.RotatedResources.namespace_mappings:type_name -> policy.kasregistry.ChangeMappings + 56, // 56: policy.kasregistry.RotateKeyResponse.kas_key:type_name -> policy.KasKey + 39, // 57: policy.kasregistry.RotateKeyResponse.rotated_resources:type_name -> policy.kasregistry.RotatedResources + 42, // 58: policy.kasregistry.ListPublicKeyMappingResponse.PublicKeyMapping.public_keys:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.PublicKey + 53, // 59: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.key:type_name -> policy.Key + 43, // 60: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.values:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.Association + 43, // 61: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.definitions:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.Association + 43, // 62: policy.kasregistry.ListPublicKeyMappingResponse.PublicKey.namespaces:type_name -> policy.kasregistry.ListPublicKeyMappingResponse.Association + 54, // 63: policy.kasregistry.RotateKeyRequest.NewKey.algorithm:type_name -> policy.Algorithm + 55, // 64: policy.kasregistry.RotateKeyRequest.NewKey.key_mode:type_name -> policy.KeyMode + 50, // 65: policy.kasregistry.RotateKeyRequest.NewKey.metadata:type_name -> common.MetadataMutable + 2, // 66: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServers:input_type -> policy.kasregistry.ListKeyAccessServersRequest + 0, // 67: policy.kasregistry.KeyAccessServerRegistryService.GetKeyAccessServer:input_type -> policy.kasregistry.GetKeyAccessServerRequest + 4, // 68: policy.kasregistry.KeyAccessServerRegistryService.CreateKeyAccessServer:input_type -> policy.kasregistry.CreateKeyAccessServerRequest + 6, // 69: policy.kasregistry.KeyAccessServerRegistryService.UpdateKeyAccessServer:input_type -> policy.kasregistry.UpdateKeyAccessServerRequest + 8, // 70: policy.kasregistry.KeyAccessServerRegistryService.DeleteKeyAccessServer:input_type -> policy.kasregistry.DeleteKeyAccessServerRequest + 26, // 71: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServerGrants:input_type -> policy.kasregistry.ListKeyAccessServerGrantsRequest + 28, // 72: policy.kasregistry.KeyAccessServerRegistryService.CreateKey:input_type -> policy.kasregistry.CreateKeyRequest + 30, // 73: policy.kasregistry.KeyAccessServerRegistryService.GetKey:input_type -> policy.kasregistry.GetKeyRequest + 32, // 74: policy.kasregistry.KeyAccessServerRegistryService.ListKeys:input_type -> policy.kasregistry.ListKeysRequest + 34, // 75: policy.kasregistry.KeyAccessServerRegistryService.UpdateKey:input_type -> policy.kasregistry.UpdateKeyRequest + 37, // 76: policy.kasregistry.KeyAccessServerRegistryService.RotateKey:input_type -> policy.kasregistry.RotateKeyRequest + 3, // 77: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServers:output_type -> policy.kasregistry.ListKeyAccessServersResponse + 1, // 78: policy.kasregistry.KeyAccessServerRegistryService.GetKeyAccessServer:output_type -> policy.kasregistry.GetKeyAccessServerResponse + 5, // 79: policy.kasregistry.KeyAccessServerRegistryService.CreateKeyAccessServer:output_type -> policy.kasregistry.CreateKeyAccessServerResponse + 7, // 80: policy.kasregistry.KeyAccessServerRegistryService.UpdateKeyAccessServer:output_type -> policy.kasregistry.UpdateKeyAccessServerResponse + 9, // 81: policy.kasregistry.KeyAccessServerRegistryService.DeleteKeyAccessServer:output_type -> policy.kasregistry.DeleteKeyAccessServerResponse + 27, // 82: policy.kasregistry.KeyAccessServerRegistryService.ListKeyAccessServerGrants:output_type -> policy.kasregistry.ListKeyAccessServerGrantsResponse + 29, // 83: policy.kasregistry.KeyAccessServerRegistryService.CreateKey:output_type -> policy.kasregistry.CreateKeyResponse + 31, // 84: policy.kasregistry.KeyAccessServerRegistryService.GetKey:output_type -> policy.kasregistry.GetKeyResponse + 33, // 85: policy.kasregistry.KeyAccessServerRegistryService.ListKeys:output_type -> policy.kasregistry.ListKeysResponse + 35, // 86: policy.kasregistry.KeyAccessServerRegistryService.UpdateKey:output_type -> policy.kasregistry.UpdateKeyResponse + 40, // 87: policy.kasregistry.KeyAccessServerRegistryService.RotateKey:output_type -> policy.kasregistry.RotateKeyResponse + 77, // [77:88] is the sub-list for method output_type + 66, // [66:77] is the sub-list for method input_type + 66, // [66:66] is the sub-list for extension type_name + 66, // [66:66] is the sub-list for extension extendee + 0, // [0:66] is the sub-list for field type_name } func init() { file_policy_kasregistry_key_access_server_registry_proto_init() } @@ -4217,7 +4394,7 @@ func file_policy_kasregistry_key_access_server_registry_proto_init() { } } file_policy_kasregistry_key_access_server_registry_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RotateKeyResponse); i { + switch v := v.(*ChangeMappings); i { case 0: return &v.state case 1: @@ -4229,7 +4406,7 @@ func file_policy_kasregistry_key_access_server_registry_proto_init() { } } file_policy_kasregistry_key_access_server_registry_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPublicKeyMappingResponse_PublicKeyMapping); i { + switch v := v.(*RotatedResources); i { case 0: return &v.state case 1: @@ -4241,7 +4418,7 @@ func file_policy_kasregistry_key_access_server_registry_proto_init() { } } file_policy_kasregistry_key_access_server_registry_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPublicKeyMappingResponse_PublicKey); i { + switch v := v.(*RotateKeyResponse); i { case 0: return &v.state case 1: @@ -4253,7 +4430,7 @@ func file_policy_kasregistry_key_access_server_registry_proto_init() { } } file_policy_kasregistry_key_access_server_registry_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPublicKeyMappingResponse_Association); i { + switch v := v.(*ListPublicKeyMappingResponse_PublicKeyMapping); i { case 0: return &v.state case 1: @@ -4265,6 +4442,30 @@ func file_policy_kasregistry_key_access_server_registry_proto_init() { } } file_policy_kasregistry_key_access_server_registry_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPublicKeyMappingResponse_PublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_policy_kasregistry_key_access_server_registry_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPublicKeyMappingResponse_Association); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_policy_kasregistry_key_access_server_registry_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RotateKeyRequest_NewKey); i { case 0: return &v.state @@ -4319,7 +4520,7 @@ func file_policy_kasregistry_key_access_server_registry_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_policy_kasregistry_key_access_server_registry_proto_rawDesc, NumEnums: 0, - NumMessages: 43, + NumMessages: 45, NumExtensions: 0, NumServices: 1, }, diff --git a/service/integration/kas_registry_key_test.go b/service/integration/kas_registry_key_test.go index 553154a32a..11ea532953 100644 --- a/service/integration/kas_registry_key_test.go +++ b/service/integration/kas_registry_key_test.go @@ -6,10 +6,13 @@ import ( "log/slog" "testing" + "github.com/google/uuid" "github.com/opentdf/platform/protocol/go/common" "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/policy/attributes" "github.com/opentdf/platform/protocol/go/policy/kasregistry" "github.com/opentdf/platform/protocol/go/policy/keymanagement" + "github.com/opentdf/platform/protocol/go/policy/namespaces" "github.com/opentdf/platform/service/internal/fixtures" "github.com/opentdf/platform/service/pkg/db" "github.com/stretchr/testify/suite" @@ -26,6 +29,10 @@ const ( notFoundKasUUID = "123e4567-e89b-12d3-a456-426614174000" privateKeyCtx = `{"key":"value"}` providerConfigID = "123e4567-e89b-12d3-a456-426614174000" + rotateKey = "rotate_key" + nonRotateKey = "non_rotate_key" + rotatePrefix = "rotate_" + nonRotatePrefix = "non_rotate_" ) type KasRegistryKeySuite struct { @@ -450,3 +457,490 @@ func (s *KasRegistryKeySuite) Test_ListKeys_KasID_Limit_Success() { s.Equal(int32(1), resp.GetPagination().GetNextOffset()) s.Equal(int32(0), resp.GetPagination().GetCurrentOffset()) } + +func (s *KasRegistryKeySuite) setupNamespaceForRotate(numNSToRotate, numNSToNotRotate int, keyToRotate, secondKey *policy.AsymmetricKey) map[string][]*policy.Namespace { + namespacesToRotate := make([]*policy.Namespace, numNSToRotate) + namespacesToNotRotate := make([]*policy.Namespace, numNSToNotRotate) + + for i := 0; i < numNSToRotate+numNSToNotRotate; i++ { + if i < numNSToRotate { + // Create a namespace + nsReq := namespaces.CreateNamespaceRequest{ + Name: rotatePrefix + uuid.New().String(), + } + namespaceWithKeyToRotate, err := s.db.PolicyClient.CreateNamespace(s.ctx, &nsReq) + s.Require().NoError(err) + s.NotNil(namespaceWithKeyToRotate) + + assignKeyReq := namespaces.NamespaceKey{ + NamespaceId: namespaceWithKeyToRotate.GetId(), + KeyId: keyToRotate.GetId(), + } + namespace, err := s.db.PolicyClient.AssignPublicKeyToNamespace(s.ctx, &assignKeyReq) + s.Require().NoError(err) + s.NotNil(namespace) + + namespacesToRotate[i] = namespaceWithKeyToRotate + } else { + nsReq2 := namespaces.CreateNamespaceRequest{ + Name: nonRotatePrefix + uuid.New().String(), + } + namespaceWithoutKeyToRotate, err := s.db.PolicyClient.CreateNamespace(s.ctx, &nsReq2) + s.Require().NoError(err) + s.NotNil(namespaceWithoutKeyToRotate) + + assignKeyReq2 := namespaces.NamespaceKey{ + NamespaceId: namespaceWithoutKeyToRotate.GetId(), + KeyId: secondKey.GetId(), + } + namespace2, err := s.db.PolicyClient.AssignPublicKeyToNamespace(s.ctx, &assignKeyReq2) + s.Require().NoError(err) + s.NotNil(namespace2) + namespacesToNotRotate[i-numNSToRotate] = namespaceWithoutKeyToRotate + } + } + return map[string][]*policy.Namespace{ + rotateKey: namespacesToRotate, + nonRotateKey: namespacesToNotRotate, + } +} + +func (s *KasRegistryKeySuite) setupKeysForRotate(kasID string) map[string]*policy.KasKey { + // Create a key for the KAS + keyReq := kasregistry.CreateKeyRequest{ + KasId: kasID, + KeyId: "original_key_id_to_rotate", + KeyAlgorithm: policy.Algorithm_ALGORITHM_RSA_2048, + KeyMode: policy.KeyMode_KEY_MODE_REMOTE, + PublicKeyCtx: []byte(`{"key":"original"}`), + } + keyToRotate, err := s.db.PolicyClient.CreateKey(s.ctx, &keyReq) + s.Require().NoError(err) + s.NotNil(rotateKey) + + keyReq2 := kasregistry.CreateKeyRequest{ + KasId: kasID, + KeyId: "second_original_key_id", + KeyAlgorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_REMOTE, + PublicKeyCtx: []byte(`{"key":"original"}`), + } + secondKey, err := s.db.PolicyClient.CreateKey(s.ctx, &keyReq2) + s.Require().NoError(err) + s.NotNil(secondKey) + + return map[string]*policy.KasKey{ + rotateKey: keyToRotate.GetKasKey(), + nonRotateKey: secondKey.GetKasKey(), + } +} + +func (s *KasRegistryKeySuite) setupAttributesForRotate(numAttrsToRotate, numAttrsToNotRotate, numAttrValuesToRotate, numAttrsValuesToNotRotate int, namespaceMap map[string][]*policy.Namespace, keyToRotate, keyNotRotated *policy.AsymmetricKey) map[string][]*policy.Attribute { + attributesToRotate := make([]*policy.Attribute, numAttrsToRotate) + attributesToNotRotate := make([]*policy.Attribute, numAttrsToNotRotate) + + if (numAttrValuesToRotate > 1 && numAttrsToRotate == 0) || (numAttrsValuesToNotRotate > 1 && numAttrsToNotRotate == 0) { + s.Fail("Invalid test setup: if there are multiple attribute values, there must be at least on attribute") + } + + if len(namespaceMap[rotateKey]) == 0 || len(namespaceMap[nonRotateKey]) == 0 { + s.Fail("Should at least have one namespace for rotating and non-rotating") + } + + for i := 0; i < numAttrsToRotate+numAttrsToNotRotate; i++ { + if i < numAttrsToRotate { + attrValueNames := make([]string, 0) + if i == 0 { + // Create all the attribute values for the first attribute + for j := 0; j < numAttrValuesToRotate; j++ { + attrValueNames = append(attrValueNames, rotatePrefix+uuid.NewString()) + } + } + + // Create a namespace + attrReq := attributes.CreateAttributeRequest{ + NamespaceId: namespaceMap[rotateKey][0].GetId(), + Name: rotatePrefix + uuid.NewString(), + Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF, + Values: attrValueNames, + } + rotateAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attrReq) + s.Require().NoError(err) + s.NotNil(rotateAttr) + + assignKeyToAttrReq := attributes.AttributeKey{ + AttributeId: rotateAttr.GetId(), + KeyId: keyToRotate.GetId(), + } + attribute, err := s.db.PolicyClient.AssignPublicKeyToAttribute(s.ctx, &assignKeyToAttrReq) + s.Require().NoError(err) + s.NotNil(attribute) + + attributesToRotate[i] = rotateAttr + } else { + attrValueNames := make([]string, 0) + if i-numAttrValuesToRotate == 0 { + // Create all the attribute values for the first attribute + for j := 0; j < numAttrValuesToRotate; j++ { + attrValueNames = append(attrValueNames, nonRotatePrefix+uuid.NewString()) + } + } + attrReq := attributes.CreateAttributeRequest{ + NamespaceId: namespaceMap[nonRotateKey][0].GetId(), + Name: nonRotatePrefix + uuid.NewString(), + Rule: policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF, + Values: attrValueNames, + } + noRotateAttr, err := s.db.PolicyClient.CreateAttribute(s.ctx, &attrReq) + s.Require().NoError(err) + s.NotNil(noRotateAttr) + + assignKeyToAttrReq := attributes.AttributeKey{ + AttributeId: noRotateAttr.GetId(), + KeyId: keyNotRotated.GetId(), + } + attribute, err := s.db.PolicyClient.AssignPublicKeyToAttribute(s.ctx, &assignKeyToAttrReq) + s.Require().NoError(err) + s.NotNil(attribute) + attributesToNotRotate[i-numAttrsToNotRotate] = noRotateAttr + } + } + // Go through and assing the values to public keys + for _, value := range attributesToRotate[0].GetValues() { + if value.GetId() == "" { + continue + } + assignKeyToAttrValueReq := attributes.ValueKey{ + ValueId: value.GetId(), + KeyId: keyToRotate.GetId(), + } + _, err := s.db.PolicyClient.AssignPublicKeyToValue(s.ctx, &assignKeyToAttrValueReq) + s.Require().NoError(err) + } + for _, value := range attributesToNotRotate[0].GetValues() { + if value.GetId() == "" { + continue + } + assignKeyToAttrValueReq := attributes.ValueKey{ + ValueId: value.GetId(), + KeyId: keyNotRotated.GetId(), + } + _, err := s.db.PolicyClient.AssignPublicKeyToValue(s.ctx, &assignKeyToAttrValueReq) + s.Require().NoError(err) + } + + return map[string][]*policy.Attribute{ + rotateKey: attributesToRotate, + nonRotateKey: attributesToNotRotate, + } +} + +func (s *KasRegistryKeySuite) cleanupRotate(attrValueIDs []string, namespaceIDs []string, attributeIDs []string, keyIDs []string, keyAccessServerIDs []string) { + for _, id := range attrValueIDs { + _, err := s.db.PolicyClient.DeleteAttributeValue(s.ctx, id) + s.Require().NoError(err) + } + for _, id := range namespaceIDs { + _, err := s.db.PolicyClient.DeleteNamespace(s.ctx, id) + s.Require().NoError(err) + } + for _, id := range attributeIDs { + _, err := s.db.PolicyClient.DeleteAttribute(s.ctx, id) + s.Require().NoError(err) + } + for _, id := range keyIDs { + _, err := s.db.PolicyClient.DeleteKey(s.ctx, id) + s.Require().NoError(err) + } + for _, id := range keyAccessServerIDs { + _, err := s.db.PolicyClient.DeleteKeyAccessServer(s.ctx, id) + s.Require().NoError(err) + } +} + +func (s *KasRegistryKeySuite) Test_RotateKey_Multiple_Attributes_Values_Namespaces_Success() { + // Create a new KAS server + kasReq := kasregistry.CreateKeyAccessServerRequest{ + Name: "test_rotate_key_kas", + Uri: "https://test-rotate-key.opentdf.io", + } + kas, err := s.db.PolicyClient.CreateKeyAccessServer(s.ctx, &kasReq) + s.Require().NoError(err) + s.NotNil(kas) + + keyMap := s.setupKeysForRotate(kas.GetId()) + namespaceMap := s.setupNamespaceForRotate(1, 1, keyMap[rotateKey].GetKey(), keyMap[nonRotateKey].GetKey()) + attributeMap := s.setupAttributesForRotate(1, 1, 1, 1, namespaceMap, keyMap[rotateKey].GetKey(), keyMap[nonRotateKey].GetKey()) + + newKey := kasregistry.RotateKeyRequest_NewKey{ + KeyId: "new_key_id", + Algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: []byte(`{"key": "new"}`), + } + + rotatedInKey, err := s.db.PolicyClient.RotateKey(s.ctx, keyMap[rotateKey], &newKey) + s.Require().NoError(err) + s.NotNil(rotatedInKey) + + // Validate the rotated key + s.Equal(newKey.GetKeyId(), rotatedInKey.GetKasKey().GetKey().GetKeyId()) + s.Equal(newKey.GetAlgorithm(), rotatedInKey.GetKasKey().GetKey().GetKeyAlgorithm()) + s.Equal(newKey.GetKeyMode(), rotatedInKey.GetKasKey().GetKey().GetKeyMode()) + s.Equal(newKey.GetPublicKeyCtx(), rotatedInKey.GetKasKey().GetKey().GetPublicKeyCtx()) + s.Equal(policy.KeyStatus_KEY_STATUS_ACTIVE, rotatedInKey.GetKasKey().GetKey().GetKeyStatus()) + + // Validate the rotated resources in the response. + s.Equal(rotatedInKey.GetRotatedResources().GetRotatedOutKey().GetKey().GetId(), keyMap[rotateKey].GetKey().GetId()) + s.Len(rotatedInKey.GetRotatedResources().GetAttributeDefinitionMappings(), 1) + s.Len(rotatedInKey.GetRotatedResources().GetNamespaceMappings(), 1) + s.Len(rotatedInKey.GetRotatedResources().GetAttributeValueMappings(), 1) + s.Equal(attributeMap[rotateKey][0].GetId(), rotatedInKey.GetRotatedResources().GetAttributeDefinitionMappings()[0].GetId()) + s.Equal(attributeMap[rotateKey][0].GetFqn(), rotatedInKey.GetRotatedResources().GetAttributeDefinitionMappings()[0].GetFqn()) + s.Equal(namespaceMap[rotateKey][0].GetId(), rotatedInKey.GetRotatedResources().GetNamespaceMappings()[0].GetId()) + s.Equal(namespaceMap[rotateKey][0].GetFqn(), rotatedInKey.GetRotatedResources().GetNamespaceMappings()[0].GetFqn()) + s.Equal(attributeMap[rotateKey][0].GetValues()[0].GetId(), rotatedInKey.GetRotatedResources().GetAttributeValueMappings()[0].GetId()) + s.Equal(attributeMap[rotateKey][0].GetValues()[0].GetFqn(), rotatedInKey.GetRotatedResources().GetAttributeValueMappings()[0].GetFqn()) + + // Verify that the old key is now inactive + oldKey, err := s.db.PolicyClient.GetKey(s.ctx, &kasregistry.GetKeyRequest_Id{ + Id: keyMap[rotateKey].GetKey().GetId(), + }) + s.Require().NoError(err) + s.Equal(policy.KeyStatus_KEY_STATUS_INACTIVE, oldKey.GetKey().GetKeyStatus()) + + // Verify that namespace has the new key + updatedNs, err := s.db.PolicyClient.GetNamespace(s.ctx, namespaceMap[rotateKey][0].GetId()) + s.Require().NoError(err) + s.Len(updatedNs.GetKasKeys(), 1) + s.Equal(rotatedInKey.GetKasKey().GetKey().GetId(), updatedNs.GetKasKeys()[0].GetKey().GetId()) + + // Verify that namespace which was assigned a key that was not rotated is still intact + nonUpdatedNs, err := s.db.PolicyClient.GetNamespace(s.ctx, namespaceMap[nonRotateKey][0].GetId()) + s.Require().NoError(err) + s.Len(nonUpdatedNs.GetKasKeys(), 1) + s.Equal(keyMap[nonRotateKey].GetKey().GetId(), nonUpdatedNs.GetKasKeys()[0].GetKey().GetId()) + + // Verify that attribute has the new key + updatedAttr, err := s.db.PolicyClient.GetAttribute(s.ctx, &attributes.GetAttributeRequest_AttributeId{ + AttributeId: attributeMap[rotateKey][0].GetId(), + }) + s.Require().NoError(err) + s.Len(updatedAttr.GetKasKeys(), 1) + s.Equal(rotatedInKey.GetKasKey().GetKey().GetId(), updatedAttr.GetKasKeys()[0].GetKey().GetId()) + + // Verify that attribute definition which was assigned a key that was not rotated is still intact + nonUpdatedAttr, err := s.db.PolicyClient.GetAttribute(s.ctx, &attributes.GetAttributeRequest_AttributeId{ + AttributeId: attributeMap[nonRotateKey][0].GetId(), + }) + s.Require().NoError(err) + s.Len(nonUpdatedAttr.GetKasKeys(), 1) + s.Equal(keyMap[nonRotateKey].GetKey().GetId(), nonUpdatedAttr.GetKasKeys()[0].GetKey().GetId()) + + // Verify that attribute value has the new key + attrValue, err := s.db.PolicyClient.GetAttributeValue(s.ctx, &attributes.GetAttributeValueRequest_ValueId{ + ValueId: attributeMap[rotateKey][0].GetValues()[0].GetId(), + }) + s.Require().NoError(err) + s.Len(attrValue.GetKasKeys(), 1) + s.Equal(rotatedInKey.GetKasKey().GetKey().GetId(), attrValue.GetKasKeys()[0].GetKey().GetId()) + + // Verify that attribute value which was assigned a key that was not rotated is still intact + nonUpdatedAttrValue, err := s.db.PolicyClient.GetAttributeValue(s.ctx, &attributes.GetAttributeValueRequest_ValueId{ + ValueId: attributeMap[nonRotateKey][0].GetValues()[0].GetId(), + }) + s.Require().NoError(err) + s.Len(nonUpdatedAttrValue.GetKasKeys(), 1) + s.Equal(keyMap[nonRotateKey].GetKey().GetId(), nonUpdatedAttrValue.GetKasKeys()[0].GetKey().GetId()) + + // Clean up + s.cleanupRotate( + []string{attrValue.GetId(), nonUpdatedAttrValue.GetId()}, + []string{namespaceMap[rotateKey][0].GetId(), namespaceMap[nonRotateKey][0].GetId()}, + []string{attributeMap[rotateKey][0].GetId(), attributeMap[nonRotateKey][0].GetId()}, + []string{keyMap[rotateKey].GetKey().GetId(), keyMap[nonRotateKey].GetKey().GetId(), rotatedInKey.GetKasKey().GetKey().GetId()}, + []string{kas.GetId()}, + ) +} + +// Should probably add a test where there are more than one of each attribute granularity to be rotated and make sure I get them +// For example, 2 attributes, 0 namespaces, 1 attribute value. +func (s *KasRegistryKeySuite) Test_RotateKey_Two_Attribute_Two_Namespace_0_AttributeValue_Success() { + // Create a new KAS server + kasReq := kasregistry.CreateKeyAccessServerRequest{ + Name: "test_rotate_key_kas", + Uri: "https://test-rotate-key.opentdf.io", + } + kas, err := s.db.PolicyClient.CreateKeyAccessServer(s.ctx, &kasReq) + s.Require().NoError(err) + s.NotNil(kas) + + keyMap := s.setupKeysForRotate(kas.GetId()) + namespaceMap := s.setupNamespaceForRotate(2, 2, keyMap[rotateKey].GetKey(), keyMap[nonRotateKey].GetKey()) + attributeMap := s.setupAttributesForRotate(2, 2, 0, 0, namespaceMap, keyMap[rotateKey].GetKey(), keyMap[nonRotateKey].GetKey()) + + newKey := kasregistry.RotateKeyRequest_NewKey{ + KeyId: "new_key_id", + Algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: []byte(`{"key": "new"}`), + } + + rotatedInKey, err := s.db.PolicyClient.RotateKey(s.ctx, keyMap[rotateKey], &newKey) + s.Require().NoError(err) + s.NotNil(rotatedInKey) + + // Validate the rotated key + s.Equal(newKey.GetKeyId(), rotatedInKey.GetKasKey().GetKey().GetKeyId()) + s.Equal(newKey.GetAlgorithm(), rotatedInKey.GetKasKey().GetKey().GetKeyAlgorithm()) + s.Equal(newKey.GetKeyMode(), rotatedInKey.GetKasKey().GetKey().GetKeyMode()) + s.Equal(newKey.GetPublicKeyCtx(), rotatedInKey.GetKasKey().GetKey().GetPublicKeyCtx()) + s.Equal(policy.KeyStatus_KEY_STATUS_ACTIVE, rotatedInKey.GetKasKey().GetKey().GetKeyStatus()) + + // Validate the rotated resources in the response. + s.Equal(rotatedInKey.GetRotatedResources().GetRotatedOutKey().GetKey().GetId(), keyMap[rotateKey].GetKey().GetId()) + s.Len(rotatedInKey.GetRotatedResources().GetAttributeDefinitionMappings(), 2) + s.Len(rotatedInKey.GetRotatedResources().GetNamespaceMappings(), 2) + s.Empty(rotatedInKey.GetRotatedResources().GetAttributeValueMappings()) + + rotatedAttributeIDs := make([]string, 0) + rotatedAttributeFQNs := make([]string, 0) + for _, rotatedAttribute := range rotatedInKey.GetRotatedResources().GetAttributeDefinitionMappings() { + rotatedAttributeIDs = append(rotatedAttributeIDs, rotatedAttribute.GetId()) + rotatedAttributeFQNs = append(rotatedAttributeFQNs, rotatedAttribute.GetFqn()) + } + for _, attr := range attributeMap[rotateKey] { + s.Contains(rotatedAttributeIDs, attr.GetId()) + s.Contains(rotatedAttributeFQNs, attr.GetFqn()) + } + + rotatedNamespaceIDs := make([]string, 0) + rotatedNamespaceFQNs := make([]string, 0) + for _, rotatedNamespace := range rotatedInKey.GetRotatedResources().GetNamespaceMappings() { + rotatedNamespaceIDs = append(rotatedNamespaceIDs, rotatedNamespace.GetId()) + rotatedNamespaceFQNs = append(rotatedNamespaceFQNs, rotatedNamespace.GetFqn()) + } + for _, ns := range namespaceMap[rotateKey] { + s.Contains(rotatedNamespaceIDs, ns.GetId()) + s.Contains(rotatedNamespaceFQNs, ns.GetFqn()) + } + + // Verify that the old key is now inactive + oldKey, err := s.db.PolicyClient.GetKey(s.ctx, &kasregistry.GetKeyRequest_Id{ + Id: keyMap[rotateKey].GetKey().GetId(), + }) + s.Require().NoError(err) + s.Equal(policy.KeyStatus_KEY_STATUS_INACTIVE, oldKey.GetKey().GetKeyStatus()) + + // Verify that namespace has the new key + for _, ns := range namespaceMap[rotateKey] { + updatedNs, err := s.db.PolicyClient.GetNamespace(s.ctx, ns.GetId()) + s.Require().NoError(err) + s.Len(updatedNs.GetKasKeys(), 1) + s.Equal(rotatedInKey.GetKasKey().GetKey().GetId(), updatedNs.GetKasKeys()[0].GetKey().GetId()) + } + + // Verify that namespace which was assigned a key that was not rotated is still intact + for _, ns := range namespaceMap[nonRotateKey] { + nonUpdatedNs, err := s.db.PolicyClient.GetNamespace(s.ctx, ns.GetId()) + s.Require().NoError(err) + s.Len(nonUpdatedNs.GetKasKeys(), 1) + s.Equal(keyMap[nonRotateKey].GetKey().GetId(), nonUpdatedNs.GetKasKeys()[0].GetKey().GetId()) + } + + // Verify that attribute has the new key + for _, attr := range attributeMap[rotateKey] { + updatedAttr, err := s.db.PolicyClient.GetAttribute(s.ctx, &attributes.GetAttributeRequest_AttributeId{ + AttributeId: attr.GetId(), + }) + s.Require().NoError(err) + s.Len(updatedAttr.GetKasKeys(), 1) + s.Equal(rotatedInKey.GetKasKey().GetKey().GetId(), updatedAttr.GetKasKeys()[0].GetKey().GetId()) + } + + // Verify that attribute definition which was assigned a key that was not rotated is still intact + for _, attr := range attributeMap[nonRotateKey] { + nonUpdatedAttr, err := s.db.PolicyClient.GetAttribute(s.ctx, &attributes.GetAttributeRequest_AttributeId{ + AttributeId: attr.GetId(), + }) + s.Require().NoError(err) + s.Len(nonUpdatedAttr.GetKasKeys(), 1) + s.Equal(keyMap[nonRotateKey].GetKey().GetId(), nonUpdatedAttr.GetKasKeys()[0].GetKey().GetId()) + } + + // Clean up + namespaceIDs := make([]string, 0) + attributeIDs := make([]string, 0) + for _, ns := range namespaceMap[rotateKey] { + namespaceIDs = append(namespaceIDs, ns.GetId()) + } + for _, ns := range namespaceMap[nonRotateKey] { + namespaceIDs = append(namespaceIDs, ns.GetId()) + } + for _, attr := range attributeMap[rotateKey] { + attributeIDs = append(attributeIDs, attr.GetId()) + } + for _, attr := range attributeMap[nonRotateKey] { + attributeIDs = append(attributeIDs, attr.GetId()) + } + + s.cleanupRotate( + []string{}, + namespaceIDs, + attributeIDs, + []string{keyMap[rotateKey].GetKey().GetId(), keyMap[nonRotateKey].GetKey().GetId(), rotatedInKey.GetKasKey().GetKey().GetId()}, + []string{kas.GetId()}, + ) +} + +func (s *KasRegistryKeySuite) Test_RotateKey_NoAttributeKeyMapping_Success() { + kasReq := kasregistry.CreateKeyAccessServerRequest{ + Name: "test_rotate_key_kas", + Uri: "https://test-rotate-key.opentdf.io", + } + kas, err := s.db.PolicyClient.CreateKeyAccessServer(s.ctx, &kasReq) + s.Require().NoError(err) + s.NotNil(kas) + + keyMap := s.setupKeysForRotate(kas.GetId()) + newKey := kasregistry.RotateKeyRequest_NewKey{ + KeyId: "new_key_id", + Algorithm: policy.Algorithm_ALGORITHM_RSA_2048, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: []byte(`{"key": "new"}`), + } + rotatedInKey, err := s.db.PolicyClient.RotateKey(s.ctx, keyMap[rotateKey], &newKey) + s.Require().NoError(err) + s.NotNil(rotatedInKey) + s.Equal(newKey.GetKeyId(), rotatedInKey.GetKasKey().GetKey().GetKeyId()) + s.Equal(newKey.GetAlgorithm(), rotatedInKey.GetKasKey().GetKey().GetKeyAlgorithm()) + s.Equal(newKey.GetKeyMode(), rotatedInKey.GetKasKey().GetKey().GetKeyMode()) + s.Equal(newKey.GetPublicKeyCtx(), rotatedInKey.GetKasKey().GetKey().GetPublicKeyCtx()) + s.Equal(policy.KeyStatus_KEY_STATUS_ACTIVE, rotatedInKey.GetKasKey().GetKey().GetKeyStatus()) + + // Validate the rotated resoureces in the response. + s.Equal(rotatedInKey.GetRotatedResources().GetRotatedOutKey().GetKey().GetId(), keyMap[rotateKey].GetKey().GetId()) + s.Empty(rotatedInKey.GetRotatedResources().GetAttributeDefinitionMappings()) + s.Empty(rotatedInKey.GetRotatedResources().GetNamespaceMappings()) + s.Empty(rotatedInKey.GetRotatedResources().GetAttributeValueMappings()) + + // Verify that the old key is now inactive + oldKey, err := s.db.PolicyClient.GetKey(s.ctx, &kasregistry.GetKeyRequest_Id{ + Id: keyMap[rotateKey].GetKey().GetId(), + }) + s.Require().NoError(err) + s.Equal(policy.KeyStatus_KEY_STATUS_INACTIVE, oldKey.GetKey().GetKeyStatus()) + + // Clean up + s.cleanupRotate( + []string{}, + []string{}, + []string{}, + []string{ + keyMap[rotateKey].GetKey().GetId(), + keyMap[nonRotateKey].GetKey().GetId(), + rotatedInKey.GetKasKey().GetKey().GetId(), + }, + []string{kas.GetId()}, + ) +} diff --git a/service/logger/audit/constants.go b/service/logger/audit/constants.go index 102cdeb8e7..d420b95b5d 100644 --- a/service/logger/audit/constants.go +++ b/service/logger/audit/constants.go @@ -70,6 +70,7 @@ const ( ActionTypeUpdate ActionTypeDelete ActionTypeRewrap + ActionTypeRotate ) func (at ActionType) String() string { @@ -79,6 +80,7 @@ func (at ActionType) String() string { "update", "delete", "rewrap", + "rotate", }[at] } diff --git a/service/pkg/db/errors.go b/service/pkg/db/errors.go index a601f68580..66c85e58ee 100644 --- a/service/pkg/db/errors.go +++ b/service/pkg/db/errors.go @@ -28,6 +28,7 @@ var ( ErrSelectIdentifierInvalid = errors.New("ErrSelectIdentifierInvalid: invalid identifier value for select query") ErrUnknownSelectIdentifier = errors.New("ErrUnknownSelectIdentifier: unknown identifier type for select query") ErrCannotUpdateToUnspecified = errors.New("ErrCannotUpdateToUnspecified: cannot update to unspecified value") + ErrKeyRotationFailed = errors.New("ErrTextKeyRotationFailed: key rotation failed") ) // Get helpful error message for PostgreSQL violation @@ -108,6 +109,7 @@ const ( ErrTextInvalidIdentifier = "value sepcified as the identifier is invalid" ErrorTextUnknownIdentifier = "could not match identifier to known type" ErrorTextUpdateToUnspecified = "cannot update to unspecified value" + ErrTextKeyRotationFailed = "key rotation failed" ) func StatusifyError(err error, fallbackErr string, log ...any) error { @@ -152,6 +154,10 @@ func StatusifyError(err error, fallbackErr string, log ...any) error { slog.Error(ErrorTextUpdateToUnspecified, l...) return connect.NewError(connect.CodeInvalidArgument, errors.New(ErrorTextUpdateToUnspecified)) } + if errors.Is(err, ErrKeyRotationFailed) { + slog.Error(ErrTextKeyRotationFailed, l...) + return connect.NewError(connect.CodeInternal, errors.New(ErrTextKeyRotationFailed)) + } slog.Error(err.Error(), l...) return connect.NewError(connect.CodeInternal, errors.New(fallbackErr)) } diff --git a/service/policy/db/key_access_server_registry.go b/service/policy/db/key_access_server_registry.go index 05138b1797..c424b84dac 100644 --- a/service/policy/db/key_access_server_registry.go +++ b/service/policy/db/key_access_server_registry.go @@ -8,12 +8,20 @@ import ( "github.com/opentdf/platform/protocol/go/common" "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/policy/attributes" "github.com/opentdf/platform/protocol/go/policy/kasregistry" "github.com/opentdf/platform/protocol/go/policy/keymanagement" + "github.com/opentdf/platform/protocol/go/policy/namespaces" "github.com/opentdf/platform/service/pkg/db" "google.golang.org/protobuf/encoding/protojson" ) +type rotatedMappingIDs struct { + NamespaceIDs []string + AttributeDefIDs []string + AttributeValueIDs []string +} + func (c PolicyDBClient) ListKeyAccessServers(ctx context.Context, r *kasregistry.ListKeyAccessServersRequest) (*kasregistry.ListKeyAccessServersResponse, error) { limit, offset := c.getRequestedLimitOffset(r.GetPagination()) @@ -654,3 +662,136 @@ func (c PolicyDBClient) DeleteKey(ctx context.Context, id string) (*policy.Asymm Id: id, }, nil } + +func (c PolicyDBClient) RotateKey(ctx context.Context, activeKey *policy.KasKey, newKey *kasregistry.RotateKeyRequest_NewKey) (*kasregistry.RotateKeyResponse, error) { + rotateKeyResp := &kasregistry.RotateKeyResponse{ + RotatedResources: &kasregistry.RotatedResources{ + AttributeDefinitionMappings: make([]*kasregistry.ChangeMappings, 0), + AttributeValueMappings: make([]*kasregistry.ChangeMappings, 0), + NamespaceMappings: make([]*kasregistry.ChangeMappings, 0), + }, + } + + // Step 1: Update old key to inactive. + rotatedOutKey, err := c.UpdateKey(ctx, &kasregistry.UpdateKeyRequest{ + Id: activeKey.GetKey().GetId(), + KeyStatus: policy.KeyStatus_KEY_STATUS_INACTIVE, + }) + if err != nil { + return nil, err + } + + // Step 2: Create new key. + newKasKey, err := c.CreateKey(ctx, &kasregistry.CreateKeyRequest{ + KasId: activeKey.GetKasId(), + KeyId: newKey.GetKeyId(), + KeyAlgorithm: newKey.GetAlgorithm(), + KeyMode: newKey.GetKeyMode(), + PublicKeyCtx: newKey.GetPublicKeyCtx(), + PrivateKeyCtx: newKey.GetPrivateKeyCtx(), + ProviderConfigId: newKey.GetProviderConfigId(), + Metadata: newKey.GetMetadata(), + }) + if err != nil { + return nil, err + } + + // Step 3: Update Namespace/Attribute/Value tables to use the new key. + rotatedIDs, err := c.rotatePublicKeyTables(ctx, activeKey.GetKey().GetId(), newKasKey.GetKasKey().GetKey().GetId()) + if err != nil { + return nil, err + } + + // Step 4: Populate the rotated resources. + if err := c.populateChangeMappings(ctx, rotatedIDs, rotateKeyResp.GetRotatedResources()); err != nil { + return nil, err + } + rotateKeyResp.RotatedResources.RotatedOutKey = rotatedOutKey + + // Step 5: Populate the new key + rotateKeyResp.KasKey = newKasKey.GetKasKey() + + return rotateKeyResp, nil +} + +func (c PolicyDBClient) populateChangeMappings(ctx context.Context, rotatedIDs rotatedMappingIDs, rotatedResources *kasregistry.RotatedResources) error { + for _, id := range rotatedIDs.NamespaceIDs { + mapping := &kasregistry.ChangeMappings{ + Id: id, + } + ns, err := c.GetNamespace(ctx, &namespaces.GetNamespaceRequest_NamespaceId{ + NamespaceId: id, + }) + if err != nil { + return err + } + mapping.Fqn = ns.GetFqn() + rotatedResources.NamespaceMappings = append(rotatedResources.GetNamespaceMappings(), mapping) + } + for _, id := range rotatedIDs.AttributeDefIDs { + mapping := &kasregistry.ChangeMappings{ + Id: id, + } + attrDef, err := c.GetAttribute(ctx, &attributes.GetAttributeRequest_AttributeId{ + AttributeId: id, + }) + if err != nil { + return err + } + mapping.Fqn = attrDef.GetFqn() + rotatedResources.AttributeDefinitionMappings = append(rotatedResources.GetAttributeDefinitionMappings(), mapping) + } + for _, id := range rotatedIDs.AttributeValueIDs { + mapping := &kasregistry.ChangeMappings{ + Id: id, + } + attrVal, err := c.GetAttributeValue(ctx, &attributes.GetAttributeValueRequest_ValueId{ + ValueId: id, + }) + if err != nil { + return err + } + mapping.Fqn = attrVal.GetFqn() + rotatedResources.AttributeValueMappings = append(rotatedResources.GetAttributeValueMappings(), mapping) + } + + return nil +} + +/** +* Rotate the public key in the Namespace, AttributeDefinition, and AttributeValue tables. + */ +func (c PolicyDBClient) rotatePublicKeyTables(ctx context.Context, oldKeyID, newKeyID string) (rotatedMappingIDs, error) { + var err error + rotatedIDs := rotatedMappingIDs{ + NamespaceIDs: make([]string, 0), + AttributeDefIDs: make([]string, 0), + AttributeValueIDs: make([]string, 0), + } + + rotatedIDs.NamespaceIDs, err = c.rotatePublicKeyForNamespace(ctx, rotatePublicKeyForNamespaceParams{ + OldKeyID: oldKeyID, + NewKeyID: newKeyID, + }) + if err != nil { + return rotatedIDs, db.WrapIfKnownInvalidQueryErr(err) + } + + rotatedIDs.AttributeDefIDs, err = c.rotatePublicKeyForAttributeDefinition(ctx, rotatePublicKeyForAttributeDefinitionParams{ + OldKeyID: oldKeyID, + NewKeyID: newKeyID, + }) + if err != nil { + return rotatedIDs, db.WrapIfKnownInvalidQueryErr(err) + } + + rotatedIDs.AttributeValueIDs, err = c.rotatePublicKeyForAttributeValue(ctx, rotatePublicKeyForAttributeValueParams{ + OldKeyID: oldKeyID, + NewKeyID: newKeyID, + }) + if err != nil { + return rotatedIDs, db.WrapIfKnownInvalidQueryErr(err) + } + + return rotatedIDs, nil +} diff --git a/service/policy/db/query.sql b/service/policy/db/query.sql index da38ce4407..26d766988e 100644 --- a/service/policy/db/query.sql +++ b/service/policy/db/query.sql @@ -248,6 +248,7 @@ WHERE (sqlc.narg('id')::uuid IS NULL OR kask.id = sqlc.narg('id')::uuid) AND (sqlc.narg('kas_uri')::text IS NULL OR kas.uri = sqlc.narg('kas_uri')::text) AND (sqlc.narg('kas_name')::text IS NULL OR kas.name = sqlc.narg('kas_name')::text); + -- name: updateKey :execrows UPDATE key_access_server_keys SET @@ -805,6 +806,12 @@ RETURNING *; DELETE FROM attribute_definition_public_key_map WHERE definition_id = $1 AND key_access_server_key_id = $2; +-- name: rotatePublicKeyForAttributeDefinition :many +UPDATE attribute_definition_public_key_map +SET key_access_server_key_id = sqlc.arg('new_key_id')::uuid +WHERE (key_access_server_key_id = sqlc.arg('old_key_id')::uuid) +RETURNING definition_id; + ---------------------------------------------------------------- -- ATTRIBUTE VALUES ---------------------------------------------------------------- @@ -911,6 +918,12 @@ RETURNING *; DELETE FROM attribute_value_public_key_map WHERE value_id = $1 AND key_access_server_key_id = $2; +-- name: rotatePublicKeyForAttributeValue :many +UPDATE attribute_value_public_key_map +SET key_access_server_key_id = sqlc.arg('new_key_id')::uuid +WHERE (key_access_server_key_id = sqlc.arg('old_key_id')::uuid) +RETURNING value_id; + ---------------------------------------------------------------- -- RESOURCE MAPPING GROUPS ---------------------------------------------------------------- @@ -1137,6 +1150,12 @@ RETURNING *; DELETE FROM attribute_namespace_public_key_map WHERE namespace_id = $1 AND key_access_server_key_id = $2; +-- name: rotatePublicKeyForNamespace :many +UPDATE attribute_namespace_public_key_map +SET key_access_server_key_id = sqlc.arg('new_key_id')::uuid +WHERE (key_access_server_key_id = sqlc.arg('old_key_id')::uuid) +RETURNING namespace_id; + ---------------------------------------------------------------- -- SUBJECT CONDITION SETS ---------------------------------------------------------------- diff --git a/service/policy/db/query.sql.go b/service/policy/db/query.sql.go index 6b26ec42ff..e367ddc89f 100644 --- a/service/policy/db/query.sql.go +++ b/service/policy/db/query.sql.go @@ -5072,6 +5072,120 @@ func (q *Queries) removePublicKeyFromNamespace(ctx context.Context, arg removePu return result.RowsAffected(), nil } +const rotatePublicKeyForAttributeDefinition = `-- name: rotatePublicKeyForAttributeDefinition :many +UPDATE attribute_definition_public_key_map +SET key_access_server_key_id = $1::uuid +WHERE (key_access_server_key_id = $2::uuid) +RETURNING definition_id +` + +type rotatePublicKeyForAttributeDefinitionParams struct { + NewKeyID string `json:"new_key_id"` + OldKeyID string `json:"old_key_id"` +} + +// rotatePublicKeyForAttributeDefinition +// +// UPDATE attribute_definition_public_key_map +// SET key_access_server_key_id = $1::uuid +// WHERE (key_access_server_key_id = $2::uuid) +// RETURNING definition_id +func (q *Queries) rotatePublicKeyForAttributeDefinition(ctx context.Context, arg rotatePublicKeyForAttributeDefinitionParams) ([]string, error) { + rows, err := q.db.Query(ctx, rotatePublicKeyForAttributeDefinition, arg.NewKeyID, arg.OldKeyID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []string + for rows.Next() { + var definition_id string + if err := rows.Scan(&definition_id); err != nil { + return nil, err + } + items = append(items, definition_id) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const rotatePublicKeyForAttributeValue = `-- name: rotatePublicKeyForAttributeValue :many +UPDATE attribute_value_public_key_map +SET key_access_server_key_id = $1::uuid +WHERE (key_access_server_key_id = $2::uuid) +RETURNING value_id +` + +type rotatePublicKeyForAttributeValueParams struct { + NewKeyID string `json:"new_key_id"` + OldKeyID string `json:"old_key_id"` +} + +// rotatePublicKeyForAttributeValue +// +// UPDATE attribute_value_public_key_map +// SET key_access_server_key_id = $1::uuid +// WHERE (key_access_server_key_id = $2::uuid) +// RETURNING value_id +func (q *Queries) rotatePublicKeyForAttributeValue(ctx context.Context, arg rotatePublicKeyForAttributeValueParams) ([]string, error) { + rows, err := q.db.Query(ctx, rotatePublicKeyForAttributeValue, arg.NewKeyID, arg.OldKeyID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []string + for rows.Next() { + var value_id string + if err := rows.Scan(&value_id); err != nil { + return nil, err + } + items = append(items, value_id) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const rotatePublicKeyForNamespace = `-- name: rotatePublicKeyForNamespace :many +UPDATE attribute_namespace_public_key_map +SET key_access_server_key_id = $1::uuid +WHERE (key_access_server_key_id = $2::uuid) +RETURNING namespace_id +` + +type rotatePublicKeyForNamespaceParams struct { + NewKeyID string `json:"new_key_id"` + OldKeyID string `json:"old_key_id"` +} + +// rotatePublicKeyForNamespace +// +// UPDATE attribute_namespace_public_key_map +// SET key_access_server_key_id = $1::uuid +// WHERE (key_access_server_key_id = $2::uuid) +// RETURNING namespace_id +func (q *Queries) rotatePublicKeyForNamespace(ctx context.Context, arg rotatePublicKeyForNamespaceParams) ([]string, error) { + rows, err := q.db.Query(ctx, rotatePublicKeyForNamespace, arg.NewKeyID, arg.OldKeyID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []string + for rows.Next() { + var namespace_id string + if err := rows.Scan(&namespace_id); err != nil { + return nil, err + } + items = append(items, namespace_id) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const updateCustomAction = `-- name: updateCustomAction :execrows UPDATE actions SET diff --git a/service/policy/kasregistry/key_access_server_registry.go b/service/policy/kasregistry/key_access_server_registry.go index 2c1e963b24..e553724124 100644 --- a/service/policy/kasregistry/key_access_server_registry.go +++ b/service/policy/kasregistry/key_access_server_registry.go @@ -349,7 +349,77 @@ func (s KeyAccessServerRegistry) ListKeys(ctx context.Context, r *connect.Reques return connect.NewResponse(resp), nil } -func (s KeyAccessServerRegistry) RotateKey(context.Context, *connect.Request[kasr.RotateKeyRequest]) (*connect.Response[kasr.RotateKeyResponse], error) { +func (s KeyAccessServerRegistry) RotateKey(ctx context.Context, r *connect.Request[kasr.RotateKeyRequest]) (*connect.Response[kasr.RotateKeyResponse], error) { + var resp *kasr.RotateKeyResponse + var objectID string + + switch i := r.Msg.GetActiveKey().(type) { + case *kasr.RotateKeyRequest_Id: + s.logger.Debug("Rotating key by ID", slog.String("ID", i.Id)) + objectID = i.Id + case *kasr.RotateKeyRequest_Key: + s.logger.Debug("Rotating key by Kas Key", slog.String("Active Key ID", i.Key.GetKid()), slog.String("New Key ID", r.Msg.GetNewKey().GetKeyId())) + objectID = i.Key.GetKid() + default: + return nil, connect.NewError(connect.CodeInvalidArgument, nil) + } + + auditParams := audit.PolicyEventParams{ + ActionType: audit.ActionTypeRotate, + ObjectType: audit.ObjectTypeKasRegistryKeys, + ObjectID: objectID, + } + + original, err := s.dbClient.GetKey(ctx, r.Msg.GetActiveKey()) + if err != nil { + s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) + return nil, db.StatusifyError(err, db.ErrTextGetRetrievalFailed, slog.String("keyAccessServer Keys", objectID)) + } + + auditParams.Original = &policy.KasKey{ + KasId: original.GetKasId(), + Key: &policy.AsymmetricKey{ + KeyId: original.GetKey().GetKeyId(), + KeyStatus: original.GetKey().GetKeyStatus(), + }, + } + + err = s.dbClient.RunInTx(ctx, func(txClient *policydb.PolicyDBClient) error { + resp, err = txClient.RotateKey(ctx, original, r.Msg.GetNewKey()) + if err != nil { + s.logger.Audit.PolicyCRUDFailure(ctx, auditParams) + return err + } + + auditParams.Updated = &kasr.RotateKeyResponse{ + RotatedResources: &kasr.RotatedResources{ + RotatedOutKey: &policy.KasKey{ + KasId: resp.GetRotatedResources().GetRotatedOutKey().GetKasId(), + Key: &policy.AsymmetricKey{ + KeyId: resp.GetRotatedResources().GetRotatedOutKey().GetKey().GetKeyId(), + KeyStatus: resp.GetRotatedResources().GetRotatedOutKey().GetKey().GetKeyStatus(), + }, + }, + AttributeDefinitionMappings: resp.GetRotatedResources().GetAttributeDefinitionMappings(), + NamespaceMappings: resp.GetRotatedResources().GetNamespaceMappings(), + AttributeValueMappings: resp.GetRotatedResources().GetAttributeValueMappings(), + }, + KasKey: &policy.KasKey{ + KasId: resp.GetKasKey().GetKasId(), + Key: &policy.AsymmetricKey{ + KeyId: resp.GetKasKey().GetKey().GetKeyId(), + KeyStatus: resp.GetKasKey().GetKey().GetKeyStatus(), + }, + }, + } + s.logger.Audit.PolicyCRUDSuccess(ctx, auditParams) + + return nil + }) + if err != nil { + return nil, db.StatusifyError(err, db.ErrTextKeyRotationFailed, slog.String("Active Key ID", objectID), slog.String("New Key ID", r.Msg.GetNewKey().GetKeyId())) + } + // Implementation for RotateKey - return nil, connect.NewError(connect.CodeUnimplemented, errors.New("not implemented")) + return connect.NewResponse(resp), nil } diff --git a/service/policy/kasregistry/key_access_server_registry.proto b/service/policy/kasregistry/key_access_server_registry.proto index 931f2fc638..162267dbd1 100644 --- a/service/policy/kasregistry/key_access_server_registry.proto +++ b/service/policy/kasregistry/key_access_server_registry.proto @@ -475,6 +475,7 @@ message UpdateKeyResponse { message RotateKeyRequest { // Required (Current Active Key ID) oneof active_key { + option (buf.validate.oneof).required = true; // Current Active Key UUID string id = 1 [(buf.validate.field).string.uuid = true]; // Alternative way to specify the active key using KAS ID and Key ID @@ -493,20 +494,41 @@ message RotateKeyRequest { // Required KeyMode key_mode = 3 [(buf.validate.field).enum.defined_only = true]; // Required - bytes private_key_ctx = 4; // Specific structure based on key provider implementation + bytes public_key_ctx = 4 [(buf.validate.field).bytes = {min_len: 1}]; + bytes private_key_ctx = 5; // Specific structure based on key provider implementation // Optional - bytes public_key_ctx = 5; string provider_config_id = 6; // Common metadata fields - common.Metadata metadata = 100; + common.MetadataMutable metadata = 100; + } +} + + + /** + * Simplified information about the resources that were rotated as part of the key rotation process. + */ + message ChangeMappings { + string id = 1; + string fqn = 2; } + +/* +* All resources that were rotated as part of the key rotation process +*/ +message RotatedResources { + KasKey rotated_out_key = 1; // The old key that was rotated out + repeated ChangeMappings attribute_definition_mappings = 2; + repeated ChangeMappings attribute_value_mappings = 3; + repeated ChangeMappings namespace_mappings = 4; } // Response message for the RotateKey request message RotateKeyResponse { // The newly rotated Kas Key KasKey kas_key = 1; + // All resources that were rotated as part of the key rotation process + RotatedResources rotated_resources = 2; } service KeyAccessServerRegistryService { diff --git a/service/policy/kasregistry/key_access_server_registry_keys_test.go b/service/policy/kasregistry/key_access_server_registry_keys_test.go index 47cf021d63..40b060e2de 100644 --- a/service/policy/kasregistry/key_access_server_registry_keys_test.go +++ b/service/policy/kasregistry/key_access_server_registry_keys_test.go @@ -19,9 +19,13 @@ const ( errMessageKasID = "kas_id" errMessageKeyStatus = "key_status" errMessageKeyKid = "key.kid" + errMessageNewKeyKid = "new_key.key_id" errMessageKeyName = "key.name" errMessageKeyURI = "key.uri" errMessageKeyAlgo = "key_algorithm" + errMessageNewKeyAlgo = "new_key.algorithm" + errMessageNewKeyMode = "new_key.key_mode" + errMessageNewKeyPubCtx = "new_key.public_key_ctx" errMessageKeyMode = "key_mode" errMessagePubKeyCtx = "public_key_ctx" errMessageKeyIdentifier = "identifier" @@ -34,9 +38,17 @@ const ( var ( validKeyCtx = []byte(`{"key": "value"}`) validMetadata = &common.MetadataMutable{} + validNewKey = &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + } ) -func Test_GetKeyAccessServer_Keys_Request(t *testing.T) { +func Test_GetKeyAccessServer_Keys(t *testing.T) { testCases := []struct { name string req *kasregistry.GetKeyRequest @@ -371,3 +383,191 @@ func Test_ListKeyAccessServer_Keys(t *testing.T) { }) } } + +func Test_RotateKeyAccessServer_Keys(t *testing.T) { + testCases := []struct { + name string + req *kasregistry.RotateKeyRequest + expectError bool + errorMessage string + }{ + { + name: "Invalid Request (empty identifier)", + req: &kasregistry.RotateKeyRequest{ + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: true, + errorMessage: errMessageRequired, + }, + { + name: "Invalid Active Key ID (invalid uuid)", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Id{ + Id: invalidUUID, + }, + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: true, + errorMessage: errMessageUUID, + }, + { + name: "Invalid Active Key - Missing identifier", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Key{ + Key: &kasregistry.KasKeyIdentifier{}, + }, + NewKey: validNewKey, + }, + expectError: true, + errorMessage: errMessageKeyIdentifier, + }, + { + name: "Invalid Active KasId", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Key{ + Key: &kasregistry.KasKeyIdentifier{ + Identifier: &kasregistry.KasKeyIdentifier_KasId{ + KasId: invalidUUID, + }, + Kid: validKeyID, + }, + }, + NewKey: validNewKey, + }, + expectError: true, + errorMessage: errMessageKasID, + }, + { + name: "Invalid Active KeyID - Missing", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Key{ + Key: &kasregistry.KasKeyIdentifier{ + Identifier: &kasregistry.KasKeyIdentifier_KasId{ + KasId: validUUID, + }, + }, + }, + NewKey: validNewKey, + }, + expectError: true, + errorMessage: errMessageKeyKid, + }, + { + name: "Invalid New Key - KeyID", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Id{ + Id: validUUID, + }, + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: true, + errorMessage: errMessageNewKeyKid, + }, + { + name: "Invalid New Key - Algorithm", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Id{ + Id: validUUID, + }, + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: -1, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: true, + errorMessage: errMessageNewKeyAlgo, + }, + { + name: "Invalid New Key - KeyMode", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Id{ + Id: validUUID, + }, + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: -1, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: true, + errorMessage: errMessageNewKeyMode, + }, + { + name: "Invalid New Key - PublicKeyCtx", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Id{ + Id: validUUID, + }, + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: true, + errorMessage: errMessageNewKeyPubCtx, + }, + { + name: "Valid Rotate Request", + req: &kasregistry.RotateKeyRequest{ + ActiveKey: &kasregistry.RotateKeyRequest_Id{ + Id: validUUID, + }, + NewKey: &kasregistry.RotateKeyRequest_NewKey{ + KeyId: validKeyID, + Algorithm: policy.Algorithm_ALGORITHM_EC_P256, + KeyMode: policy.KeyMode_KEY_MODE_LOCAL, + PublicKeyCtx: validKeyCtx, + PrivateKeyCtx: validKeyCtx, + Metadata: validMetadata, + }, + }, + expectError: false, + }, + } + + v := getValidator() // Get the validator instance (assuming this is defined elsewhere) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := v.Validate(tc.req) + if tc.expectError { + require.Error(t, err, "Expected error for test case: %s", tc.name) + if tc.errorMessage != "" { + require.Contains(t, err.Error(), tc.errorMessage, "Expected error message to contain '%s' for test case: %s", tc.errorMessage, tc.name) + } + } else { + require.NoError(t, err, "Expected no error for test case: %s", tc.name) + } + }) + } +}