diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 9cc721b7b..4cb83eb79 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -9,28 +9,14 @@ on: - opened - synchronize - reopened - paths-ignore: - - '**/*.md' - - LICENSE - - CODEOWNERS push: branches: - main - paths-ignore: - - '**/*.md' - - LICENSE - - CODEOWNERS merge_group: branches: - main types: - checks_requested - paths: - - '**' - - '!**/*.md' - - 'docs/**' - - '!LICENSE' - - '!CODEOWNERS' workflow_call: jobs: diff --git a/.github/workflows/git-town.yaml b/.github/workflows/git-town.yaml new file mode 100644 index 000000000..2a07e9408 --- /dev/null +++ b/.github/workflows/git-town.yaml @@ -0,0 +1,22 @@ +name: Git Town + +on: + pull_request: + branches: + - '**' + +jobs: + git-town: + name: Display the branch stack + runs-on: ubuntu-22.04 + + permissions: + contents: read + pull-requests: write + + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 + - uses: git-town/action@7cec053e109396e49a15328a749b32552e6f91db + with: + skip-single-stacks: true + main-branch: main diff --git a/.release-please-manifest.json b/.release-please-manifest.json index df429b859..5ba034386 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -3,6 +3,6 @@ "lib/ocrypto": "0.1.6", "lib/flattening": "0.1.1", "protocol/go": "0.2.18", - "sdk": "0.3.16", - "service": "0.4.25" + "sdk": "0.3.17", + "service": "0.4.26" } diff --git a/docs/configuration.md b/docs/configuration.md index 3441fe72e..fb2f8b5f6 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -66,23 +66,24 @@ The server configuration is used to define how the application runs its server. Root level key `server` -| Field | Description | Default | Environment Variable | -| --------------------- | ----------------------------------------------------------------- | ------- | -------------------- | -| `auth.audience` | The audience for the IDP. | | OPENTDF_SERVER_AUTH_AUDIENCE | -| `auth.issuer` | The issuer for the IDP. | | OPENTDF_SERVER_AUTH_ISSUER | -| `auth.cache_refresh` | Interval in which the IDP jwks should be refreshed | `15m` | OPENTDF_SERVER_AUTH_CACHE_REFRESH | -| `auth.dpopskew` | The amount of time drift allowed between when the client generated a dpop proof and the server time. | `1h` | OPENTDF_SERVER_AUTH | -| `auth.skew` | The amount of time drift allowed between a tokens `exp` claim and the server time. | `1m` | OPENTDF_SERVER_AUTH_SKEW | -| `auth.public_client_id` | The oidc client id. This is leveraged by otdfctl. | | OPENTDF_SERVER_AUTH_PUBLIC_CLIENT_ID | -| `auth.enforceDPoP` | If true, DPoP bindings on Access Tokens are enforced. | `false` | OPENTDF_SERVER_AUTH_ENFORCEDPOP | -| `cryptoProvider` | A list of public/private keypairs and their use. Described [below](#crypto-provider) | empty | | -| `enable_pprof` | Enable golang performance profiling | `false` | OPENTDF_SERVER_ENABLE_PPROF | -| `grpc.reflection` | The configuration for the grpc server. | `true` | OPENTDF_SERVER_GRPC_REFLECTION | -| `host` | The host address for the server. | `""` | OPENTDF_SERVER_HOST | -| `port` | The port number for the server. | `9000` | OPENTDF_SERVER_PORT | -| `tls.enabled` | Enable tls. | `false` | OPENTDF_SERVER_TLS_ENABLED | -| `tls.cert` | The path to the tls certificate. | | OPENTDF_SERVER_TLS_CERT | -| `tls.key` | The path to the tls key. | | OPENTDF_SERVER_TLS_KEY | +| Field | Description | Default | Environment Variable | +|-------------------------|---------------------------------------------------------------------------------------------------------------|---------|--------------------------------------| +| `auth.audience` | The audience for the IDP. | | OPENTDF_SERVER_AUTH_AUDIENCE | +| `auth.issuer` | The issuer for the IDP. | | OPENTDF_SERVER_AUTH_ISSUER | +| `auth.policy` | The Casbin policy for enforcing authorization on endpoints. Described [below](#casbin-endpoint-authorization) | | | +| `auth.cache_refresh` | Interval in which the IDP jwks should be refreshed | `15m` | OPENTDF_SERVER_AUTH_CACHE_REFRESH | +| `auth.dpopskew` | The amount of time drift allowed between when the client generated a dpop proof and the server time. | `1h` | OPENTDF_SERVER_AUTH | +| `auth.skew` | The amount of time drift allowed between a tokens `exp` claim and the server time. | `1m` | OPENTDF_SERVER_AUTH_SKEW | +| `auth.public_client_id` | The oidc client id. This is leveraged by otdfctl. | | OPENTDF_SERVER_AUTH_PUBLIC_CLIENT_ID | +| `auth.enforceDPoP` | If true, DPoP bindings on Access Tokens are enforced. | `false` | OPENTDF_SERVER_AUTH_ENFORCEDPOP | +| `cryptoProvider` | A list of public/private keypairs and their use. Described [below](#crypto-provider) | empty | | +| `enable_pprof` | Enable golang performance profiling | `false` | OPENTDF_SERVER_ENABLE_PPROF | +| `grpc.reflection` | The configuration for the grpc server. | `true` | OPENTDF_SERVER_GRPC_REFLECTION | +| `host` | The host address for the server. | `""` | OPENTDF_SERVER_HOST | +| `port` | The port number for the server. | `9000` | OPENTDF_SERVER_PORT | +| `tls.enabled` | Enable tls. | `false` | OPENTDF_SERVER_TLS_ENABLED | +| `tls.cert` | The path to the tls certificate. | | OPENTDF_SERVER_TLS_CERT | +| `tls.key` | The path to the tls key. | | OPENTDF_SERVER_TLS_KEY | Example: @@ -216,4 +217,91 @@ services: rego: path: /path/to/policy.rego query: data.opentdf.entitlements.attributes -``` \ No newline at end of file +``` + +### Casbin Endpoint Authorization + +OpenTDF uses Casbin to manage authorization policies. This document provides an overview of how to configure and manage the default authorization policy in OpenTDF. + +#### Key Aspects of Authorization Configuration + +1. **Default Role**: The default role assigned to an authorized user if no specific role is found. +2. **Claim**: The claim in the OIDC token that should be used to map roles. +3. **Map**: Mapping between policy roles and IdP roles. +4. **CSV**: The authorization policy in CSV format. +5. **Model**: The Casbin policy model. + +#### Configuration in opentdf-example.yaml + +Below is an example configuration snippet from +opentdf-example.yaml: + +```yaml +server: + auth: + enabled: true + enforceDPoP: false + public_client_id: 'opentdf-public' + audience: 'http://localhost:8080' + issuer: http://keycloak:8888/auth/realms/opentdf + policy: + ## Default role for all requests + default: "role:standard" + + ## Dot notation is used to access nested claims (i.e. realm_access.roles) + claim: "realm_access.roles" + + ## Maps the external role to the OpenTDF role + ## Note: left side is used in the policy, right side is the external role + map: + standard: opentdf-standard + admin: opentdf-admin + org-admin: opentdf-org-admin + + ## Custom policy (see examples https://github.com/casbin/casbin/tree/master/examples) + csv: | + p, role:org-admin, policy:attributes, *, *, allow + p, role:org-admin, policy:subject-mappings, *, *, allow + p, role:org-admin, policy:resource-mappings, *, *, allow + p, role:org-admin, policy:kas-registry, *, *, allow + p, role:org-admin, policy:unsafe, *, *, allow + p, role:admin, policy:attributes, read, allow + p, role:admin, policy:subject-mappings, read, allow + p, role:admin, policy:resource-mappings, read, allow + p, role:admin, policy:kas-registry, read, allow + p, role:standard, policy:attributes, read, allow + p, role:standard, policy:subject-mappings, read, allow + p, role:standard, policy:resource-mappings, read, allow + p, role:standard, policy:kas-registry, read, allow + p, role:unknown, entityresolution.EntityResolutionService.ResolveEntities, write, allow + p, role:unknown, kas.AccessService/Rewrap, *, allow + + ## Custom model (see https://casbin.org/docs/syntax-for-models/) + model: | + [request_definition] + r = sub, res, act, obj + + [policy_definition] + p = sub, res, act, obj, eft + + [role_definition] + g = _, _ + + [policy_effect] + e = some(where (p.eft == allow)) && !some(where (p.eft == deny)) + + [matchers] + m = g(r.sub, p.sub) && globOrRegexMatch(r.res, p.res) && globOrRegexMatch(r.act, p.act) && globOrRegexMatch(r.obj, p.obj) +``` + +#### Role Permissions + +- **Org Admin**: Can read, write, and perform unsafe mutations. +- **Admin**: Can read and write. +- **Standard User**: Can read. +- **Public Endpoints**: Accessible without specific roles. + +#### Managing Authorization Policy + +Admins can manage the authorization policy directly in the YAML configuration file. For detailed configuration options, refer to the [Casbin documentation](https://casbin.org/docs/en/syntax-for-models). + diff --git a/docs/grpc/index.html b/docs/grpc/index.html index da4ba9685..4b621e563 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -948,6 +948,14 @@

Table of Contents

MCreateSubjectMappingResponse +
  • + MDeleteAllUnmappedSubjectConditionSetsRequest +
  • + +
  • + MDeleteAllUnmappedSubjectConditionSetsResponse +
  • +
  • MDeleteSubjectConditionSetRequest
  • @@ -1478,7 +1486,7 @@

    Attribute

    Condition

    -

    A Condition defines a rule of

    Example: Subjects with a field selected by the flattened selector "'.division'" and a value of "Accounting" or "Marketing":

    {

    "subject_external_selector_value": "'.division'",

    "operator": "SUBJECT_MAPPING_OPERATOR_ENUM_IN",

    "subject_external_values" : ["Accounting", "Marketing"]

    }

    Example: Subjects that are not part of the Fantastic Four according to their alias field:

    {

    "subject_external_selector_value": "'.data[0].alias'",

    "operator": "SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN",

    "subject_external_values" : ["mister_fantastic", "the_thing", "human_torch", "invisible_woman"]

    }

    +

    A Condition defines a rule of

    @@ -1641,6 +1649,14 @@

    KeyAccessServer

    + + + + + + + @@ -3754,7 +3770,7 @@

    AssignKeyAcce

    - + @@ -3802,7 +3818,7 @@

    AssignKeyAccessSe

    - + @@ -3850,14 +3866,14 @@

    AttributeKeyAccessServer

    attribute_id - + - + @@ -3888,21 +3904,22 @@

    CreateAttributeRequest

    - + - + - @@ -3965,14 +3982,15 @@

    CreateAttributeValueReque

    - + - + @@ -4020,7 +4038,7 @@

    DeactivateAttributeRequest

    - + @@ -4068,7 +4086,7 @@

    DeactivateAttributeVa

    - + @@ -4116,7 +4134,7 @@

    GetAttributeRequest

    - + @@ -4164,7 +4182,7 @@

    GetAttributeValueRequest

    id - + @@ -4220,7 +4238,8 @@

    GetAttributeValuesByF

    - + @@ -4330,14 +4349,15 @@

    ListAttributeValuesRequest

    - + - + @@ -4385,14 +4405,16 @@

    ListAttributesRequest

    - + - + @@ -4440,7 +4462,7 @@

    RemoveKeyAc

    - + @@ -4488,7 +4510,7 @@

    RemoveKeyAccess

    - + @@ -4598,14 +4620,15 @@

    UpdateAttributeValueReque

    - + - + @@ -4660,14 +4683,14 @@

    ValueKeyAccessServer

    - + - + @@ -5003,7 +5026,14 @@

    CreateKeyAccessServerRe

    - + + + + + + + + @@ -5058,7 +5088,7 @@

    DeleteKeyAccessServerRe

    - + @@ -5106,7 +5136,7 @@

    GetKeyAccessServerRequest<

    - + @@ -5231,7 +5261,7 @@

    ListKeyAccessServer

    @@ -5239,7 +5269,18 @@

    ListKeyAccessServer

    - + + + + + + + + @@ -5325,21 +5366,29 @@

    UpdateKeyAccessServerRe

    - + - + + + + + + + + - + @@ -5643,7 +5692,7 @@

    DeactivateNamespaceRequest

    - + @@ -5674,7 +5723,7 @@

    GetNamespaceRequest

    - + @@ -5722,7 +5771,8 @@

    ListNamespacesRequest

    - + @@ -5770,14 +5820,14 @@

    NamespaceKeyAccessServer

    namespace_id - + - + @@ -6083,7 +6133,7 @@

    CreateResource

    - + @@ -6125,7 +6175,7 @@

    CreateResourc

    CreateResourceMappingRequest

    -

    ### Request

    grpcurl -plaintext -d @ localhost:8080 policy.resourcemapping.ResourceMappingService/CreateResourceMapping <

    {

    "mapping": {

    "name": "Classification",

    "attribute_value_id": "12345678-1234-1234-1234-123456789012",

    "terms": ["CONFIDENTIAL", "CONTROLLED UNCLASSIFIED", "OFFICIAL-SENSITIVE", "CUI", "C"]

    }

    }

    EOM

    ### Response

    {

    "mapping": {

    "metadata": {

    "id": "12345678-1234-1234-1234-123456789012",

    "created_at": "2020-01-01T00:00:00Z",

    "updated_at": "2020-01-01T00:00:00Z"

    },

    "name": "Classification",

    "attribute_value_id": "12345678-1234-1234-1234-123456789012",

    "terms": ["CONFIDENTIAL", "CONTROLLED UNCLASSIFIED", "OFFICIAL-SENSITIVE", "CUI", "C"]

    }

    }

    +

    namestring

    Optional +Unique name of the KAS instance

    metadata common.Metadataattribute_key_access_server AttributeKeyAccessServer

    Required

    value_key_access_server ValueKeyAccessServer

    Required

    string

    Required

    key_access_server_id string

    Required

    name string

    Required

    rule policy.AttributeRuleTypeEnum

    Required

    values string repeated

    Optional attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character. +

    Optional +Attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character. The stored attribute value will be normalized to lower case.

    value string

    Required

    metadata common.MetadataMutable

    Common metadata

    Optional +Common metadata

    id string

    Required

    id string

    Required

    id string

    Required

    string

    Required

    with_value policy.AttributeValueSelector

    Optional +This attribute value selector is not used currently, but left here for future use.

    attribute_id string

    Required

    state common.ActiveStateEnum

    ACTIVE by default when not specified

    Optional +ACTIVE by default when not specified

    state common.ActiveStateEnum

    ACTIVE by default when not specified

    Optional +ACTIVE by default when not specified

    namespace string

    can be id or name

    Optional +Namespace ID or name

    attribute_key_access_server AttributeKeyAccessServer

    Required

    value_key_access_server ValueKeyAccessServer

    Required

    id string

    Required

    metadata common.MetadataMutable

    Common metadata

    Optional +Common metadata

    value_id string

    Required

    key_access_server_id string

    Required

    public_key policy.PublicKey

    Required

    namestring

    Optional

    id string

    Required

    id string

    Required

    string

    Optional -Filter LIST by either ID or URI of a registered Key Access Server. +Filter LIST by ID of a registered Key Access Server. If neither is provided, grants from all registered KASs to policy attribute objects are returned.

    kas_uri string

    Optional +Filter LIST by URI of a registered Key Access Server. +If none is provided, grants from all registered KASs to policy attribute objects are returned.

    kas_namestring

    Optional +Filter LIST by name of a registered Key Access Server. +If none are provided, grants from all registered KASs to policy attribute objects are returned.

    uri string

    Optional

    public_key policy.PublicKey

    Optional

    namestring

    Optional

    metadata common.MetadataMutable

    Common metadata

    Optional +Common metadata

    id string

    Required

    id string

    Required

    state common.ActiveStateEnum

    ACTIVE by default when not specified

    Optional +ACTIVE by default when not specified

    string

    Required

    key_access_server_id string

    Required

    name string

    Required

    @@ -6145,7 +6195,7 @@

    CreateResourceMappi

    - + @@ -6159,7 +6209,7 @@

    CreateResourceMappi

    - + @@ -6620,7 +6670,7 @@

    UpdateResource

    - + @@ -6696,21 +6746,22 @@

    UpdateResourceMappi

    - + - + - + @@ -7052,7 +7103,8 @@

    CreateSubjectMappingR

    - + @@ -7108,6 +7160,37 @@

    CreateSubjectMapping +

    DeleteAllUnmappedSubjectConditionSetsRequest

    +

    Prune any Subject Condition Sets not utilized within a Subject Mapping

    + + + + + +

    DeleteAllUnmappedSubjectConditionSetsResponse

    +

    + + +
    terms string repeated

    Required

    metadata common.MetadataMutable

    Optional

    name string

    Optional

    terms string repeated

    Optional

    group_id string

    Optional

    metadata common.MetadataMutable

    Common Metadata

    Optional +Common Metadata

    actions policy.Action repeated

    The actions permitted by subjects in this mapping

    Required +The actions permitted by subjects in this mapping

    + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    subject_condition_setspolicy.SubjectConditionSetrepeated

    Only IDs of any deleted Subject Condition Set provided

    + + + + +

    DeleteSubjectConditionSetRequest

    @@ -7122,7 +7205,7 @@

    DeleteSubjectCon id string -

    +

    Required

    @@ -7170,7 +7253,7 @@

    DeleteSubjectMappingR id string -

    +

    Required

    @@ -7218,7 +7301,7 @@

    GetSubjectCondition id string -

    +

    Required

    @@ -7273,7 +7356,7 @@

    GetSubjectMappingRequest id string -

    +

    Required

    @@ -7370,7 +7453,7 @@

    ListSubjectMappingsRe

    MatchSubjectMappingsRequest

    -

    MatchSubjectMappingsRequest liberally returns a list of SubjectMappings based on the provided SubjectProperties. The SubjectMappings are returned

    if there is any single condition found among the structures that matches for one of the provided properties:

    1. The external selector value, external value, and an IN operator

    2. The external selector value, _no_ external value, and a NOT_IN operator

    Without this filtering, if a selector value was something like '.emailAddress' or '.username', every Subject is probably going to relate to that mapping

    in some way or another, potentially matching every single attribute in the DB if a policy admin has relied heavily on that field. There is no

    logic applied beyond a single condition within the query to avoid business logic interpreting the supplied conditions beyond the bare minimum

    initial filter.

    NOTE: if you have any issues, debug logs are available within the service to help identify why a mapping was or was not returned.

    +

    MatchSubjectMappingsRequest liberally returns a list of SubjectMappings based on the provided SubjectProperties.

    The SubjectMappings are returned if an external selector field matches.

    @@ -7548,7 +7631,8 @@

    UpdateSubjectMappingR

    - + @@ -7687,6 +7771,13 @@

    SubjectMappingService

    + + + + + + +
    actions policy.Action repeated

    Replaces entire list of actions permitted by subjects

    Optional +Replaces entire list of actions permitted by subjects

    DeleteAllUnmappedSubjectConditionSetsDeleteAllUnmappedSubjectConditionSetsRequestDeleteAllUnmappedSubjectConditionSetsResponse

    @@ -7815,6 +7906,16 @@

    Methods with HTTP bindings

    + + + + DeleteAllUnmappedSubjectConditionSets + DELETE + /subject-condition-sets/unmapped + + + + @@ -7849,7 +7950,8 @@

    UnsafeDeleteAttributeRequest fqn string -

    Fully Qualified Name (FQN) of Attribute Definition (i.e. https://<namespace>/attr/<attribute name>), normalized to lower case.

    +

    Required +Fully Qualified Name (FQN) of Attribute Definition (i.e. https://<namespace>/attr/<attribute name>), normalized to lower case.

    @@ -7905,7 +8007,8 @@

    UnsafeDeleteAttributeVa fqn string -

    Fully Qualified Name (FQN) of Attribute Value (i.e. https://<namespace>/attr/<attribute name>/value/<value>), normalized to lower case.

    +

    Required +Fully Qualified Name (FQN) of Attribute Value (i.e. https://<namespace>/attr/<attribute name>/value/<value>), normalized to lower case.

    @@ -7961,7 +8064,8 @@

    UnsafeDeleteNamespaceRequest fqn string -

    Fully Qualified Name (FQN) of Namespace (i.e. https://<namespace>), normalized to lower case.

    +

    Required +Fully Qualified Name (FQN) of Namespace (i.e. https://<namespace>), normalized to lower case.

    @@ -8009,7 +8113,7 @@

    UnsafeReactivateAttribut id string -

    +

    Required

    @@ -8057,7 +8161,7 @@

    UnsafeReactivateAtt id string -

    +

    Required

    @@ -8105,7 +8209,7 @@

    UnsafeReactivateNamespac id string -

    +

    Required

    @@ -8169,7 +8273,8 @@

    UnsafeUpdateAttributeRequest rule policy.AttributeRuleTypeEnum -

    WARNING!! +

    Optional +WARNING!! Updating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name.

    @@ -8177,7 +8282,8 @@

    UnsafeUpdateAttributeRequest values_order string repeated -

    WARNING!! +

    Optional +WARNING!! Unsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition will retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted deleted, created, and unsafely re-ordered as necessary.

    @@ -8228,14 +8334,14 @@

    UnsafeUpdateAttributeVa id string -

    +

    Required

    value string -

    +

    Required

    @@ -8290,7 +8396,7 @@

    UnsafeUpdateNamespaceRequest name string -

    +

    Required

    diff --git a/docs/openapi/policy/attributes/attributes.swagger.json b/docs/openapi/policy/attributes/attributes.swagger.json index 17e5248ca..0dcf82f16 100644 --- a/docs/openapi/policy/attributes/attributes.swagger.json +++ b/docs/openapi/policy/attributes/attributes.swagger.json @@ -37,7 +37,7 @@ "parameters": [ { "name": "state", - "description": "ACTIVE by default when not specified", + "description": "Optional\nACTIVE by default when not specified", "in": "query", "required": false, "type": "string", @@ -51,7 +51,7 @@ }, { "name": "namespace", - "description": "can be id or name", + "description": "Optional\nNamespace ID or name", "in": "query", "required": false, "type": "string" @@ -171,13 +171,14 @@ "parameters": [ { "name": "attributeId", + "description": "Required", "in": "query", "required": false, "type": "string" }, { "name": "state", - "description": "ACTIVE by default when not specified", + "description": "Optional\nACTIVE by default when not specified", "in": "query", "required": false, "type": "string", @@ -216,6 +217,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -244,6 +246,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -272,6 +275,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -285,7 +289,7 @@ "properties": { "metadata": { "$ref": "#/definitions/commonMetadataMutable", - "title": "Common metadata" + "title": "Optional\nCommon metadata" }, "metadataUpdateBehavior": { "$ref": "#/definitions/commonMetadataUpdateEnum" @@ -319,12 +323,14 @@ "parameters": [ { "name": "attributeKeyAccessServer.attributeId", + "description": "Required", "in": "query", "required": false, "type": "string" }, { "name": "attributeKeyAccessServer.keyAccessServerId", + "description": "Required", "in": "query", "required": false, "type": "string" @@ -354,6 +360,7 @@ "parameters": [ { "name": "attributeKeyAccessServer", + "description": "Required", "in": "body", "required": true, "schema": { @@ -386,12 +393,14 @@ "parameters": [ { "name": "valueKeyAccessServer.valueId", + "description": "Required", "in": "query", "required": false, "type": "string" }, { "name": "valueKeyAccessServer.keyAccessServerId", + "description": "Required", "in": "query", "required": false, "type": "string" @@ -420,6 +429,7 @@ "parameters": [ { "name": "valueKeyAccessServer", + "description": "Required", "in": "body", "required": true, "schema": { @@ -465,11 +475,12 @@ "type": "object", "properties": { "value": { - "type": "string" + "type": "string", + "title": "Required" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", - "title": "Common metadata" + "title": "Optional\nCommon metadata" } } } @@ -500,6 +511,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -528,6 +540,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -630,10 +643,12 @@ "type": "object", "properties": { "attributeId": { - "type": "string" + "type": "string", + "title": "Required" }, "keyAccessServerId": { - "type": "string" + "type": "string", + "title": "Required" } } }, @@ -645,17 +660,19 @@ "title": "Required" }, "name": { - "type": "string" + "type": "string", + "title": "Required" }, "rule": { - "$ref": "#/definitions/policyAttributeRuleTypeEnum" + "$ref": "#/definitions/policyAttributeRuleTypeEnum", + "title": "Required" }, "values": { "type": "array", "items": { "type": "string" }, - "description": "Optional attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character.\nThe stored attribute value will be normalized to lower case." + "description": "Optional \nAttribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character.\nThe stored attribute value will be normalized to lower case." }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", @@ -783,10 +800,12 @@ "type": "object", "properties": { "valueId": { - "type": "string" + "type": "string", + "title": "Required" }, "keyAccessServerId": { - "type": "string" + "type": "string", + "title": "Required" } } }, @@ -961,7 +980,6 @@ "title": "list of comparison values for the result of applying the subject_external_selector_value on a flattened Entity Representation (Subject), evaluated by the operator" } }, - "description": "Example: Subjects with a field selected by the flattened selector \"'.division'\" and a value of \"Accounting\" or \"Marketing\":\n{\n\"subject_external_selector_value\": \"'.division'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_IN\",\n\"subject_external_values\" : [\"Accounting\", \"Marketing\"]\n}\n\nExample: Subjects that are not part of the Fantastic Four according to their alias field:\n{\n\"subject_external_selector_value\": \"'.data[0].alias'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN\",\n\"subject_external_values\" : [\"mister_fantastic\", \"the_thing\", \"human_torch\", \"invisible_woman\"]\n}", "title": "*\nA Condition defines a rule of \u003cthe value at the flattened 'selector value' location\u003e \u003coperator\u003e \u003csubject external values\u003e" }, "policyConditionBooleanTypeEnum": { @@ -1044,6 +1062,10 @@ "publicKey": { "$ref": "#/definitions/policyPublicKey" }, + "name": { + "type": "string", + "title": "Optional\nUnique name of the KAS instance" + }, "metadata": { "$ref": "#/definitions/commonMetadata", "title": "Common metadata" 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 bbd287d1a..ec05d19d9 100644 --- a/docs/openapi/policy/kasregistry/key_access_server_registry.swagger.json +++ b/docs/openapi/policy/kasregistry/key_access_server_registry.swagger.json @@ -88,13 +88,21 @@ "parameters": [ { "name": "kasId", - "description": "Optional\nFilter LIST by either ID or URI of a registered Key Access Server.\nIf neither is provided, grants from all registered KASs to policy attribute objects are returned.", + "description": "Optional\nFilter LIST by ID of a registered Key Access Server.\nIf neither is provided, grants from all registered KASs to policy attribute objects are returned.", "in": "query", "required": false, "type": "string" }, { "name": "kasUri", + "description": "Optional\nFilter LIST by URI of a registered Key Access Server.\nIf none is provided, grants from all registered KASs to policy attribute objects are returned.", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "kasName", + "description": "Optional\nFilter LIST by name of a registered Key Access Server.\nIf none are provided, grants from all registered KASs to policy attribute objects are returned.", "in": "query", "required": false, "type": "string" @@ -125,6 +133,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -153,6 +162,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -194,14 +204,20 @@ "type": "object", "properties": { "uri": { - "type": "string" + "type": "string", + "title": "Optional" }, "publicKey": { - "$ref": "#/definitions/policyPublicKey" + "$ref": "#/definitions/policyPublicKey", + "title": "Optional" + }, + "name": { + "type": "string", + "title": "Optional" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", - "title": "Common metadata" + "title": "Optional\nCommon metadata" }, "metadataUpdateBehavior": { "$ref": "#/definitions/commonMetadataUpdateEnum" @@ -270,7 +286,12 @@ "title": "Required" }, "publicKey": { - "$ref": "#/definitions/policyPublicKey" + "$ref": "#/definitions/policyPublicKey", + "title": "Required" + }, + "name": { + "type": "string", + "title": "Optional" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", @@ -428,6 +449,10 @@ "publicKey": { "$ref": "#/definitions/policyPublicKey" }, + "name": { + "type": "string", + "title": "Optional\nUnique name of the KAS instance" + }, "metadata": { "$ref": "#/definitions/commonMetadata", "title": "Common metadata" diff --git a/docs/openapi/policy/namespaces/namespaces.swagger.json b/docs/openapi/policy/namespaces/namespaces.swagger.json index 265549220..114dadcbc 100644 --- a/docs/openapi/policy/namespaces/namespaces.swagger.json +++ b/docs/openapi/policy/namespaces/namespaces.swagger.json @@ -36,7 +36,7 @@ "parameters": [ { "name": "state", - "description": "ACTIVE by default when not specified", + "description": "Optional\nACTIVE by default when not specified", "in": "query", "required": false, "type": "string", @@ -104,12 +104,14 @@ "parameters": [ { "name": "namespaceKeyAccessServer.namespaceId", + "description": "Required", "in": "query", "required": false, "type": "string" }, { "name": "namespaceKeyAccessServer.keyAccessServerId", + "description": "Required", "in": "query", "required": false, "type": "string" @@ -171,6 +173,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -199,6 +202,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -369,10 +373,12 @@ "type": "object", "properties": { "namespaceId": { - "type": "string" + "type": "string", + "title": "Required" }, "keyAccessServerId": { - "type": "string" + "type": "string", + "title": "Required" } } }, @@ -445,6 +451,10 @@ "publicKey": { "$ref": "#/definitions/policyPublicKey" }, + "name": { + "type": "string", + "title": "Optional\nUnique name of the KAS instance" + }, "metadata": { "$ref": "#/definitions/commonMetadata", "title": "Common metadata" diff --git a/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json b/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json index bbf657358..584016720 100644 --- a/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json +++ b/docs/openapi/policy/resourcemapping/resource_mapping.swagger.json @@ -172,7 +172,8 @@ "title": "Optional" }, "name": { - "type": "string" + "type": "string", + "title": "Optional" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", @@ -239,7 +240,6 @@ "parameters": [ { "name": "body", - "description": "grpcurl -plaintext -d @ localhost:8080 policy.resourcemapping.ResourceMappingService/CreateResourceMapping \u003c\u003cEOM\n{\n\"mapping\": {\n\"name\": \"Classification\",\n\"attribute_value_id\": \"12345678-1234-1234-1234-123456789012\",\n\"terms\": [\"CONFIDENTIAL\", \"CONTROLLED UNCLASSIFIED\", \"OFFICIAL-SENSITIVE\", \"CUI\", \"C\"]\n}\n}\nEOM\n\n### Response\n\n{\n\"mapping\": {\n\"metadata\": {\n\"id\": \"12345678-1234-1234-1234-123456789012\",\n\"created_at\": \"2020-01-01T00:00:00Z\",\n\"updated_at\": \"2020-01-01T00:00:00Z\"\n},\n\"name\": \"Classification\",\n\"attribute_value_id\": \"12345678-1234-1234-1234-123456789012\",\n\"terms\": [\"CONFIDENTIAL\", \"CONTROLLED UNCLASSIFIED\", \"OFFICIAL-SENSITIVE\", \"CUI\", \"C\"]\n}\n}", "in": "body", "required": true, "schema": { @@ -385,14 +385,16 @@ "type": "array", "items": { "type": "string" - } + }, + "title": "Optional" }, "groupId": { - "type": "string" + "type": "string", + "title": "Optional" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", - "title": "Common Metadata" + "title": "Optional\nCommon Metadata" }, "metadataUpdateBehavior": { "$ref": "#/definitions/commonMetadataUpdateEnum" @@ -550,7 +552,6 @@ "title": "list of comparison values for the result of applying the subject_external_selector_value on a flattened Entity Representation (Subject), evaluated by the operator" } }, - "description": "Example: Subjects with a field selected by the flattened selector \"'.division'\" and a value of \"Accounting\" or \"Marketing\":\n{\n\"subject_external_selector_value\": \"'.division'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_IN\",\n\"subject_external_values\" : [\"Accounting\", \"Marketing\"]\n}\n\nExample: Subjects that are not part of the Fantastic Four according to their alias field:\n{\n\"subject_external_selector_value\": \"'.data[0].alias'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN\",\n\"subject_external_values\" : [\"mister_fantastic\", \"the_thing\", \"human_torch\", \"invisible_woman\"]\n}", "title": "*\nA Condition defines a rule of \u003cthe value at the flattened 'selector value' location\u003e \u003coperator\u003e \u003csubject external values\u003e" }, "policyConditionBooleanTypeEnum": { @@ -633,6 +634,10 @@ "publicKey": { "$ref": "#/definitions/policyPublicKey" }, + "name": { + "type": "string", + "title": "Optional\nUnique name of the KAS instance" + }, "metadata": { "$ref": "#/definitions/commonMetadata", "title": "Common metadata" @@ -864,7 +869,8 @@ "title": "Required" }, "name": { - "type": "string" + "type": "string", + "title": "Required" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", @@ -891,18 +897,18 @@ "type": "array", "items": { "type": "string" - } + }, + "title": "Required" }, "groupId": { "type": "string", "title": "Optional" }, "metadata": { - "$ref": "#/definitions/commonMetadataMutable" + "$ref": "#/definitions/commonMetadataMutable", + "title": "Optional" } - }, - "description": "grpcurl -plaintext -d @ localhost:8080 policy.resourcemapping.ResourceMappingService/CreateResourceMapping \u003c\u003cEOM\n{\n\"mapping\": {\n\"name\": \"Classification\",\n\"attribute_value_id\": \"12345678-1234-1234-1234-123456789012\",\n\"terms\": [\"CONFIDENTIAL\", \"CONTROLLED UNCLASSIFIED\", \"OFFICIAL-SENSITIVE\", \"CUI\", \"C\"]\n}\n}\nEOM\n\n### Response\n\n{\n\"mapping\": {\n\"metadata\": {\n\"id\": \"12345678-1234-1234-1234-123456789012\",\n\"created_at\": \"2020-01-01T00:00:00Z\",\n\"updated_at\": \"2020-01-01T00:00:00Z\"\n},\n\"name\": \"Classification\",\n\"attribute_value_id\": \"12345678-1234-1234-1234-123456789012\",\n\"terms\": [\"CONFIDENTIAL\", \"CONTROLLED UNCLASSIFIED\", \"OFFICIAL-SENSITIVE\", \"CUI\", \"C\"]\n}\n}", - "title": "### Request" + } }, "resourcemappingCreateResourceMappingResponse": { "type": "object", diff --git a/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json b/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json index 6afccc032..57726379d 100644 --- a/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json +++ b/docs/openapi/policy/subjectmapping/subject_mapping.swagger.json @@ -68,6 +68,28 @@ ] } }, + "/subject-condition-sets/unmapped": { + "delete": { + "operationId": "SubjectMappingService_DeleteAllUnmappedSubjectConditionSets", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/subjectmappingDeleteAllUnmappedSubjectConditionSetsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "SubjectMappingService" + ] + } + }, "/subject-condition-sets/{id}": { "get": { "operationId": "SubjectMappingService_GetSubjectConditionSet", @@ -88,6 +110,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -116,6 +139,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -289,6 +313,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -317,6 +342,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -367,7 +393,7 @@ "type": "object", "$ref": "#/definitions/policyAction" }, - "title": "Replaces entire list of actions permitted by subjects" + "title": "Optional\nReplaces entire list of actions permitted by subjects" }, "metadata": { "$ref": "#/definitions/commonMetadataMutable", @@ -529,7 +555,6 @@ "title": "list of comparison values for the result of applying the subject_external_selector_value on a flattened Entity Representation (Subject), evaluated by the operator" } }, - "description": "Example: Subjects with a field selected by the flattened selector \"'.division'\" and a value of \"Accounting\" or \"Marketing\":\n{\n\"subject_external_selector_value\": \"'.division'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_IN\",\n\"subject_external_values\" : [\"Accounting\", \"Marketing\"]\n}\n\nExample: Subjects that are not part of the Fantastic Four according to their alias field:\n{\n\"subject_external_selector_value\": \"'.data[0].alias'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN\",\n\"subject_external_values\" : [\"mister_fantastic\", \"the_thing\", \"human_torch\", \"invisible_woman\"]\n}", "title": "*\nA Condition defines a rule of \u003cthe value at the flattened 'selector value' location\u003e \u003coperator\u003e \u003csubject external values\u003e" }, "policyConditionBooleanTypeEnum": { @@ -612,6 +637,10 @@ "publicKey": { "$ref": "#/definitions/policyPublicKey" }, + "name": { + "type": "string", + "title": "Optional\nUnique name of the KAS instance" + }, "metadata": { "$ref": "#/definitions/commonMetadata", "title": "Common metadata" @@ -850,7 +879,7 @@ "type": "object", "$ref": "#/definitions/policyAction" }, - "title": "The actions permitted by subjects in this mapping" + "title": "Required\nThe actions permitted by subjects in this mapping" }, "existingSubjectConditionSetId": { "type": "string", @@ -874,6 +903,19 @@ } } }, + "subjectmappingDeleteAllUnmappedSubjectConditionSetsResponse": { + "type": "object", + "properties": { + "subjectConditionSets": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/policySubjectConditionSet" + }, + "title": "Only IDs of any deleted Subject Condition Set provided" + } + } + }, "subjectmappingDeleteSubjectConditionSetResponse": { "type": "object", "properties": { diff --git a/docs/openapi/policy/unsafe/unsafe.swagger.json b/docs/openapi/policy/unsafe/unsafe.swagger.json index 977e1a582..be648ffea 100644 --- a/docs/openapi/policy/unsafe/unsafe.swagger.json +++ b/docs/openapi/policy/unsafe/unsafe.swagger.json @@ -43,7 +43,7 @@ }, { "name": "fqn", - "description": "Fully Qualified Name (FQN) of Attribute Value (i.e. https://\u003cnamespace\u003e/attr/\u003cattribute name\u003e/value/\u003cvalue\u003e), normalized to lower case.", + "description": "Required\nFully Qualified Name (FQN) of Attribute Value (i.e. https://\u003cnamespace\u003e/attr/\u003cattribute name\u003e/value/\u003cvalue\u003e), normalized to lower case.", "in": "query", "required": false, "type": "string" @@ -73,12 +73,14 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" }, { "name": "value", + "description": "Required", "in": "query", "required": false, "type": "string" @@ -109,6 +111,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -146,7 +149,7 @@ }, { "name": "fqn", - "description": "Fully Qualified Name (FQN) of Attribute Definition (i.e. https://\u003cnamespace\u003e/attr/\u003cattribute name\u003e), normalized to lower case.", + "description": "Required\nFully Qualified Name (FQN) of Attribute Definition (i.e. https://\u003cnamespace\u003e/attr/\u003cattribute name\u003e), normalized to lower case.", "in": "query", "required": false, "type": "string" @@ -190,7 +193,7 @@ }, { "name": "rule", - "description": "WARNING!! \nUpdating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name.", + "description": "Optional\nWARNING!! \nUpdating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name.", "in": "query", "required": false, "type": "string", @@ -204,7 +207,7 @@ }, { "name": "valuesOrder", - "description": "WARNING!!\nUnsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition\nwill retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted\ndeleted, created, and unsafely re-ordered as necessary.", + "description": "Optional\nWARNING!!\nUnsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition\nwill retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted\ndeleted, created, and unsafely re-ordered as necessary.", "in": "query", "required": false, "type": "array", @@ -239,6 +242,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -276,7 +280,7 @@ }, { "name": "fqn", - "description": "Fully Qualified Name (FQN) of Namespace (i.e. https://\u003cnamespace\u003e), normalized to lower case.", + "description": "Required\nFully Qualified Name (FQN) of Namespace (i.e. https://\u003cnamespace\u003e), normalized to lower case.", "in": "query", "required": false, "type": "string" @@ -313,6 +317,7 @@ }, { "name": "name", + "description": "Required", "in": "query", "required": false, "type": "string" @@ -343,6 +348,7 @@ "parameters": [ { "name": "id", + "description": "Required", "in": "path", "required": true, "type": "string" @@ -475,7 +481,6 @@ "title": "list of comparison values for the result of applying the subject_external_selector_value on a flattened Entity Representation (Subject), evaluated by the operator" } }, - "description": "Example: Subjects with a field selected by the flattened selector \"'.division'\" and a value of \"Accounting\" or \"Marketing\":\n{\n\"subject_external_selector_value\": \"'.division'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_IN\",\n\"subject_external_values\" : [\"Accounting\", \"Marketing\"]\n}\n\nExample: Subjects that are not part of the Fantastic Four according to their alias field:\n{\n\"subject_external_selector_value\": \"'.data[0].alias'\",\n\"operator\": \"SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN\",\n\"subject_external_values\" : [\"mister_fantastic\", \"the_thing\", \"human_torch\", \"invisible_woman\"]\n}", "title": "*\nA Condition defines a rule of \u003cthe value at the flattened 'selector value' location\u003e \u003coperator\u003e \u003csubject external values\u003e" }, "policyConditionBooleanTypeEnum": { @@ -558,6 +563,10 @@ "publicKey": { "$ref": "#/definitions/policyPublicKey" }, + "name": { + "type": "string", + "title": "Optional\nUnique name of the KAS instance" + }, "metadata": { "$ref": "#/definitions/commonMetadata", "title": "Common metadata" diff --git a/protocol/go/policy/attributes/attributes.pb.go b/protocol/go/policy/attributes/attributes.pb.go index 2e92b1546..ee8f59085 100644 --- a/protocol/go/policy/attributes/attributes.pb.go +++ b/protocol/go/policy/attributes/attributes.pb.go @@ -29,7 +29,9 @@ type AttributeKeyAccessServer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AttributeId string `protobuf:"bytes,1,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"` + // Required + AttributeId string `protobuf:"bytes,1,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"` + // Required KeyAccessServerId string `protobuf:"bytes,2,opt,name=key_access_server_id,json=keyAccessServerId,proto3" json:"key_access_server_id,omitempty"` } @@ -84,7 +86,9 @@ type ValueKeyAccessServer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ValueId string `protobuf:"bytes,1,opt,name=value_id,json=valueId,proto3" json:"value_id,omitempty"` + // Required + ValueId string `protobuf:"bytes,1,opt,name=value_id,json=valueId,proto3" json:"value_id,omitempty"` + // Required KeyAccessServerId string `protobuf:"bytes,2,opt,name=key_access_server_id,json=keyAccessServerId,proto3" json:"key_access_server_id,omitempty"` } @@ -139,9 +143,11 @@ type ListAttributesRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Optional // ACTIVE by default when not specified State common.ActiveStateEnum `protobuf:"varint,1,opt,name=state,proto3,enum=common.ActiveStateEnum" json:"state,omitempty"` - // can be id or name + // Optional + // Namespace ID or name Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` } @@ -243,6 +249,7 @@ type GetAttributeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -338,10 +345,13 @@ type CreateAttributeRequest struct { unknownFields protoimpl.UnknownFields // Required - NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Rule policy.AttributeRuleTypeEnum `protobuf:"varint,3,opt,name=rule,proto3,enum=policy.AttributeRuleTypeEnum" json:"rule,omitempty"` - // Optional attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character. + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + // Required + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Required + Rule policy.AttributeRuleTypeEnum `protobuf:"varint,3,opt,name=rule,proto3,enum=policy.AttributeRuleTypeEnum" json:"rule,omitempty"` + // Optional + // Attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character. // The stored attribute value will be normalized to lower case. Values []string `protobuf:"bytes,4,rep,name=values,proto3" json:"values,omitempty"` // Optional @@ -579,6 +589,7 @@ type DeactivateAttributeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -676,6 +687,7 @@ type GetAttributeValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -770,7 +782,9 @@ type ListAttributeValuesRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required AttributeId string `protobuf:"bytes,1,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"` + // Optional // ACTIVE by default when not specified State common.ActiveStateEnum `protobuf:"varint,2,opt,name=state,proto3,enum=common.ActiveStateEnum" json:"state,omitempty"` } @@ -875,7 +889,9 @@ type CreateAttributeValueRequest struct { // Required AttributeId string `protobuf:"bytes,1,opt,name=attribute_id,json=attributeId,proto3" json:"attribute_id,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // Required + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // Optional // Common metadata Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` } @@ -985,7 +1001,9 @@ type UpdateAttributeValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Optional // Common metadata Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` MetadataUpdateBehavior common.MetadataUpdateEnum `protobuf:"varint,101,opt,name=metadata_update_behavior,json=metadataUpdateBehavior,proto3,enum=common.MetadataUpdateEnum" json:"metadata_update_behavior,omitempty"` @@ -1096,6 +1114,7 @@ type DeactivateAttributeValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -1192,7 +1211,9 @@ type GetAttributeValuesByFqnsRequest struct { // Required // Fully Qualified Names of attribute values (i.e. https:///attr//value/), normalized to lower case. - Fqns []string `protobuf:"bytes,1,rep,name=fqns,proto3" json:"fqns,omitempty"` + Fqns []string `protobuf:"bytes,1,rep,name=fqns,proto3" json:"fqns,omitempty"` + // Optional + // This attribute value selector is not used currently, but left here for future use. WithValue *policy.AttributeValueSelector `protobuf:"bytes,2,opt,name=with_value,json=withValue,proto3" json:"with_value,omitempty"` } @@ -1295,6 +1316,7 @@ type AssignKeyAccessServerToAttributeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required AttributeKeyAccessServer *AttributeKeyAccessServer `protobuf:"bytes,1,opt,name=attribute_key_access_server,json=attributeKeyAccessServer,proto3" json:"attribute_key_access_server,omitempty"` } @@ -1389,6 +1411,7 @@ type RemoveKeyAccessServerFromAttributeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required AttributeKeyAccessServer *AttributeKeyAccessServer `protobuf:"bytes,1,opt,name=attribute_key_access_server,json=attributeKeyAccessServer,proto3" json:"attribute_key_access_server,omitempty"` } @@ -1483,6 +1506,7 @@ type AssignKeyAccessServerToValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required ValueKeyAccessServer *ValueKeyAccessServer `protobuf:"bytes,1,opt,name=value_key_access_server,json=valueKeyAccessServer,proto3" json:"value_key_access_server,omitempty"` } @@ -1577,6 +1601,7 @@ type RemoveKeyAccessServerFromValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required ValueKeyAccessServer *ValueKeyAccessServer `protobuf:"bytes,1,opt,name=value_key_access_server,json=valueKeyAccessServer,proto3" json:"value_key_access_server,omitempty"` } @@ -1735,133 +1760,50 @@ var file_policy_attributes_attributes_proto_rawDesc = []byte{ 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x18, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x62, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x19, 0x0a, - 0x08, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x64, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, - 0x4b, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x2d, 0x0a, 0x13, - 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x14, 0x47, - 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x22, 0xc2, 0x04, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x29, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0xaf, 0x02, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9a, 0x02, 0xba, 0x48, 0x96, 0x02, - 0xba, 0x01, 0x8a, 0x02, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, - 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, - 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, - 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, - 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, - 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, - 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, - 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0xc8, 0x01, - 0x01, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x04, - 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, 0x01, - 0x01, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x56, 0x0a, 0x06, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x42, 0x3e, 0xba, 0x48, - 0x3b, 0x92, 0x01, 0x38, 0x08, 0x00, 0x18, 0x01, 0x22, 0x32, 0x72, 0x30, 0x18, 0xfd, 0x01, 0x32, - 0x2b, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, - 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x06, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 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, 0x22, 0x4a, 0x0a, 0x17, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, - 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 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, 0x12, 0x54, 0x0a, - 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, - 0x69, 0x6f, 0x72, 0x22, 0x4a, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x18, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, + 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, + 0x39, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, + 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x14, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x12, 0x23, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x07, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, + 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x49, 0x64, 0x22, 0x64, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, + 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x4b, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, + 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, - 0x34, 0x0a, 0x1a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, - 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x1b, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x32, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x40, 0x0a, 0x19, 0x47, 0x65, 0x74, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x76, 0x0a, 0x1a, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0c, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x22, 0x44, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xc3, 0x03, 0x0a, 0x1b, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0c, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x49, 0x64, 0x12, 0xb4, 0x02, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x9d, 0x02, 0xba, 0x48, 0x99, 0x02, 0xba, 0x01, 0x8d, 0x02, 0x0a, - 0x16, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, + 0xc4, 0x04, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x0c, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0xaf, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9a, 0x02, 0xba, 0x48, 0x96, 0x02, 0xba, 0x01, 0x8a, + 0x02, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, @@ -1869,325 +1811,411 @@ var file_policy_attributes_attributes_proto_rawDesc = []byte{ 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, - 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, - 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, - 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0xc8, 0x01, 0x01, 0x72, - 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 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, - 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, - 0x43, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0xcf, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x08, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, + 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, + 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, + 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, + 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, + 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0xc8, 0x01, 0x01, 0x72, 0x03, + 0x18, 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x72, 0x75, 0x6c, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, 0x01, 0x01, 0x82, 0x01, + 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x56, 0x0a, 0x06, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x42, 0x3e, 0xba, 0x48, 0x3b, 0x92, 0x01, + 0x38, 0x08, 0x00, 0x18, 0x01, 0x22, 0x32, 0x72, 0x30, 0x18, 0xfd, 0x01, 0x32, 0x2b, 0x5e, 0x5b, + 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, + 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, + 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 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, 0x22, 0x4a, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x22, 0xbd, 0x01, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, + 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 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, 0x12, 0x54, 0x0a, 0x18, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, + 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 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, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, - 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, - 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x07, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x43, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, + 0x6f, 0x72, 0x22, 0x4a, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, + 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x36, + 0x0a, 0x1a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, + 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x1b, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x34, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, + 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x40, 0x0a, 0x19, + 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x78, + 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x0c, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0b, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, + 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x44, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xc5, + 0x03, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, + 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0b, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0xb4, 0x02, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9d, 0x02, 0xba, 0x48, + 0x99, 0x02, 0xba, 0x01, 0x8d, 0x02, 0x0a, 0x16, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, + 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, + 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, + 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, + 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, + 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, + 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, + 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, + 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, + 0x24, 0x27, 0x29, 0xc8, 0x01, 0x01, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 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, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x07, 0x6d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x43, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, 0x0a, 0x1f, 0x44, - 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, - 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x20, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x84, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x12, - 0x45, 0x0a, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x1b, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, + 0x01, 0x52, 0x02, 0x69, 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, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, + 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, + 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, + 0x43, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x1f, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x47, 0x0a, 0x20, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x1f, 0x47, + 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, + 0x0a, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0b, 0xba, 0x48, + 0x08, 0x92, 0x01, 0x05, 0x08, 0x01, 0x10, 0xfa, 0x01, 0x52, 0x04, 0x66, 0x71, 0x6e, 0x73, 0x12, + 0x3d, 0x0a, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x09, 0x77, 0x69, 0x74, - 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9b, 0x03, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, - 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x66, - 0x71, 0x6e, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, - 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x66, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x11, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x8c, 0x01, 0x0a, 0x17, 0x46, 0x71, 0x6e, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x5b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x95, 0x01, 0x0a, 0x27, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, + 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x69, 0x74, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9b, + 0x03, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x66, 0x71, 0x6e, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x4b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, + 0x66, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x41, + 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x8c, 0x01, + 0x0a, 0x17, 0x46, 0x71, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x5b, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x95, 0x01, 0x0a, + 0x27, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x22, 0x96, 0x01, 0x0a, 0x28, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, + 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x97, 0x01, + 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x2a, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x96, 0x01, 0x0a, - 0x28, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x97, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, - 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, - 0x98, 0x01, 0x0a, 0x2a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, - 0x0a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x52, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x23, 0x41, + 0x65, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x23, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x24, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, + 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, + 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x25, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, + 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, + 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x88, 0x01, + 0x0a, 0x26, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x24, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x17, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x25, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, - 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, - 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5e, 0x0a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x32, 0xc1, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x12, 0x92, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, + 0x65, 0x72, 0x52, 0x14, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xc1, 0x13, 0x0a, 0x11, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, + 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x92, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x16, 0x12, 0x14, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x79, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, - 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x12, - 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, + 0x79, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, - 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, - 0x66, 0x71, 0x6e, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8e, - 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, - 0x91, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x14, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9e, 0x01, 0x0a, 0x18, 0x47, + 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x79, + 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x42, 0x79, 0x46, 0x71, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x66, 0x71, 0x6e, 0x12, 0x80, 0x01, 0x0a, 0x0f, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, + 0x2a, 0x22, 0x0b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x85, + 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x15, 0x3a, 0x01, 0x2a, 0x32, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8e, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x91, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, + 0x12, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa5, 0x01, 0x0a, 0x14, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, - 0x32, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, 0x18, - 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, + 0x22, 0x21, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xe4, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, - 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xcd, 0x01, 0x0a, 0x22, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xdb, 0x01, 0x0a, 0x1c, - 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, 0x70, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x32, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x32, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x2a, + 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xe4, 0x01, 0x0a, + 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x41, 0x3a, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6b, 0x65, + 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, + 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x73, 0x12, 0xcd, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, + 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x2a, + 0x22, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x73, 0x12, 0xdb, 0x01, 0x0a, 0x1c, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, - 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xc8, 0x01, 0x0a, 0x1e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, 0x70, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x2a, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, - 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, - 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x0f, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, - 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, - 0x41, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x3a, 0x17, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x12, 0xc8, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, + 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x2b, 0x2a, 0x29, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, + 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, + 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x41, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0xca, 0x02, + 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go index 5a4a42233..e5797432a 100644 --- a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go +++ b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go @@ -29,6 +29,7 @@ type GetKeyAccessServerRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -209,8 +210,11 @@ type CreateKeyAccessServerRequest struct { unknownFields protoimpl.UnknownFields // Required - Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` + Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` + // Required PublicKey *policy.PublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // Optional + Name string `protobuf:"bytes,20,opt,name=name,proto3" json:"name,omitempty"` // Common metadata Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` } @@ -261,6 +265,13 @@ func (x *CreateKeyAccessServerRequest) GetPublicKey() *policy.PublicKey { return nil } +func (x *CreateKeyAccessServerRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + func (x *CreateKeyAccessServerRequest) GetMetadata() *common.MetadataMutable { if x != nil { return x.Metadata @@ -321,9 +332,14 @@ type UpdateKeyAccessServerRequest struct { unknownFields protoimpl.UnknownFields // Required - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Uri string `protobuf:"bytes,2,opt,name=uri,proto3" json:"uri,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Optional + Uri string `protobuf:"bytes,2,opt,name=uri,proto3" json:"uri,omitempty"` + // Optional PublicKey *policy.PublicKey `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // Optional + Name string `protobuf:"bytes,20,opt,name=name,proto3" json:"name,omitempty"` + // Optional // Common metadata Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` MetadataUpdateBehavior common.MetadataUpdateEnum `protobuf:"varint,101,opt,name=metadata_update_behavior,json=metadataUpdateBehavior,proto3,enum=common.MetadataUpdateEnum" json:"metadata_update_behavior,omitempty"` @@ -382,6 +398,13 @@ func (x *UpdateKeyAccessServerRequest) GetPublicKey() *policy.PublicKey { return nil } +func (x *UpdateKeyAccessServerRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + func (x *UpdateKeyAccessServerRequest) GetMetadata() *common.MetadataMutable { if x != nil { return x.Metadata @@ -448,6 +471,7 @@ type DeleteKeyAccessServerRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -674,10 +698,17 @@ type ListKeyAccessServerGrantsRequest struct { unknownFields protoimpl.UnknownFields // Optional - // Filter LIST by either ID or URI of a registered Key Access Server. + // Filter LIST by ID of a registered Key Access Server. // If neither is provided, grants from all registered KASs to policy attribute objects are returned. - KasId string `protobuf:"bytes,1,opt,name=kas_id,json=kasId,proto3" json:"kas_id,omitempty"` + KasId string `protobuf:"bytes,1,opt,name=kas_id,json=kasId,proto3" json:"kas_id,omitempty"` + // Optional + // Filter LIST by URI of a registered Key Access Server. + // If none is provided, grants from all registered KASs to policy attribute objects are returned. KasUri string `protobuf:"bytes,2,opt,name=kas_uri,json=kasUri,proto3" json:"kas_uri,omitempty"` + // Optional + // Filter LIST by name of a registered Key Access Server. + // If none are provided, grants from all registered KASs to policy attribute objects are returned. + KasName string `protobuf:"bytes,3,opt,name=kas_name,json=kasName,proto3" json:"kas_name,omitempty"` } func (x *ListKeyAccessServerGrantsRequest) Reset() { @@ -726,6 +757,13 @@ func (x *ListKeyAccessServerGrantsRequest) GetKasUri() string { return "" } +func (x *ListKeyAccessServerGrantsRequest) GetKasName() string { + if x != nil { + return x.KasName + } + return "" +} + type ListKeyAccessServerGrantsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -787,67 +825,140 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x33, 0x0a, 0x19, 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, 0x12, 0x16, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x61, 0x0a, 0x1a, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 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, 0x22, 0x65, 0x0a, 0x1c, 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, 0x12, 0x45, 0x0a, 0x12, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x10, 0x6b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, 0xa7, 0x01, - 0x0a, 0x1c, 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, 0x12, 0x18, - 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x38, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, - 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 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, 0x22, 0x64, 0x0a, 0x1d, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0f, 0x6b, 0x65, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x85, 0x02, - 0x0a, 0x1c, 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, 0x12, 0x16, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, - 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x30, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, - 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 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, 0x12, - 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, - 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x64, 0x0a, 0x1d, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x36, 0x0a, 0x1c, 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, 0x12, 0x16, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x35, 0x0a, 0x19, 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, 0x12, 0x18, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, + 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x61, 0x0a, 0x1a, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 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, 0x22, 0x65, 0x0a, 0x1c, 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, 0x12, 0x45, 0x0a, 0x12, 0x6b, 0x65, 0x79, 0x5f, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x10, 0x6b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, + 0xd8, 0x05, 0x0a, 0x1c, 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, + 0x12, 0x87, 0x02, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0xf4, + 0x01, 0xba, 0x48, 0xf0, 0x01, 0xba, 0x01, 0xec, 0x01, 0x0a, 0x0a, 0x75, 0x72, 0x69, 0x5f, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xcf, 0x01, 0x55, 0x52, 0x49, 0x20, 0x6d, 0x75, 0x73, 0x74, + 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x52, 0x4c, 0x20, + 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x2c, 0x20, 0x27, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, + 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x27, 0x29, 0x20, 0x66, 0x6f, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x45, 0x61, 0x63, + 0x68, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, + 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x63, 0x61, 0x6e, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, + 0x2c, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, + 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x0c, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x69, 0x73, + 0x55, 0x72, 0x69, 0x28, 0x29, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x38, 0x0a, 0x0a, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x12, 0xbe, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x09, 0x42, 0xa9, 0x02, 0xba, 0x48, 0xa5, 0x02, 0xba, 0x01, 0x9c, 0x02, 0x0a, 0x0f, + 0x6b, 0x61, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, + 0xb3, 0x01, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x4b, 0x41, 0x53, + 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, + 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, + 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, + 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, + 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, + 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x4b, 0x41, 0x53, 0x20, 0x6e, + 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, + 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, + 0x29, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x3f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, + 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, + 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, + 0x24, 0x27, 0x29, 0x20, 0x3a, 0x20, 0x74, 0x72, 0x75, 0x65, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0x64, 0x0a, 0x1d, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, + 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x0f, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x22, 0xe0, 0x06, 0x0a, 0x1c, 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, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, + 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xac, 0x02, 0x0a, 0x03, + 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x99, 0x02, 0xba, 0x48, 0x95, 0x02, + 0xba, 0x01, 0x91, 0x02, 0x0a, 0x13, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, + 0x72, 0x69, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xd8, 0x01, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x55, 0x52, 0x49, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, + 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x28, 0x65, 0x2e, + 0x67, 0x2e, 0x2c, 0x20, 0x27, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x6d, + 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x27, 0x29, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, + 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x73, + 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, + 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, + 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, + 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x1f, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, + 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x69, 0x73, + 0x55, 0x72, 0x69, 0x28, 0x29, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x30, 0x0a, 0x0a, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0xb9, 0x02, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0xa4, 0x02, 0xba, 0x48, + 0xa0, 0x02, 0xba, 0x01, 0x97, 0x02, 0x0a, 0x0f, 0x6b, 0x61, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x65, 0x64, 0x20, 0x4b, 0x41, 0x53, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, + 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, + 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2c, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, + 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, + 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, + 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x64, 0x20, 0x4b, 0x41, 0x53, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x4e, 0x73, + 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x7c, + 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, + 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, + 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, + 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, + 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x12, 0x54, 0x0a, + 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, + 0x69, 0x6f, 0x72, 0x22, 0x64, 0x0a, 0x1d, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0f, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x38, 0x0a, 0x1c, 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, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, 0x1d, 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, 0x12, 0x43, 0x0a, 0x11, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, @@ -879,95 +990,145 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{ 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x47, - 0x72, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x52, 0x0a, 0x20, 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, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x61, 0x73, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x61, 0x73, 0x49, 0x64, - 0x12, 0x17, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x55, 0x72, 0x69, 0x22, 0x66, 0x0a, 0x21, 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, 0x12, 0x41, - 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, - 0x73, 0x32, 0xe4, 0x07, 0x0a, 0x1e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x96, 0x01, 0x0a, 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, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x95, 0x01, - 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, - 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, - 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, - 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, - 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, - 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 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, 0xac, 0x01, 0x0a, 0x19, 0x4c, 0x69, - 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, - 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x73, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xa2, - 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, - 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xe2, - 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x22, 0xe9, 0x06, 0x0a, 0x20, 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, 0x12, 0xcb, 0x01, 0x0a, 0x06, 0x6b, + 0x61, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0xb3, 0x01, 0xba, 0x48, + 0xaf, 0x01, 0xba, 0x01, 0xab, 0x01, 0x0a, 0x14, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x5f, 0x75, 0x75, 0x69, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x23, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6d, 0x75, 0x73, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x55, 0x49, + 0x44, 0x1a, 0x6e, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3d, 0x3d, + 0x20, 0x30, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x28, 0x27, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, + 0x38, 0x7d, 0x2d, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, + 0x7d, 0x2d, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, + 0x2d, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x34, 0x7d, 0x2d, + 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x5d, 0x7b, 0x31, 0x32, 0x7d, 0x27, + 0x29, 0x52, 0x05, 0x6b, 0x61, 0x73, 0x49, 0x64, 0x12, 0xb3, 0x02, 0x0a, 0x07, 0x6b, 0x61, 0x73, + 0x5f, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x99, 0x02, 0xba, 0x48, 0x95, + 0x02, 0xba, 0x01, 0x91, 0x02, 0x0a, 0x13, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, + 0x75, 0x72, 0x69, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xd8, 0x01, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x55, 0x52, 0x49, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, + 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x28, 0x65, + 0x2e, 0x67, 0x2e, 0x2c, 0x20, 0x27, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x65, + 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x27, 0x29, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, + 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, + 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2c, 0x20, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, + 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x1f, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, + 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x69, + 0x73, 0x55, 0x72, 0x69, 0x28, 0x29, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x55, 0x72, 0x69, 0x12, 0xc0, + 0x02, 0x0a, 0x08, 0x6b, 0x61, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x42, 0xa4, 0x02, 0xba, 0x48, 0xa0, 0x02, 0xba, 0x01, 0x97, 0x02, 0x0a, 0x0f, 0x6b, 0x61, + 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x4b, 0x41, 0x53, 0x20, 0x6e, + 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, + 0x68, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, + 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, + 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, + 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x4b, 0x41, 0x53, 0x20, 0x6e, 0x61, 0x6d, + 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, + 0x73, 0x65, 0x2e, 0x1a, 0x4e, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, + 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, + 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, + 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, + 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x07, 0x6b, 0x61, 0x73, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0x66, 0x0a, 0x21, 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, 0x12, 0x41, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x32, 0xe4, 0x07, 0x0a, 0x1e, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x96, 0x01, 0x0a, + 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, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, + 0x12, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, + 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0xa1, 0x01, 0x0a, + 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x32, 0x18, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, + 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, 0xac, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, + 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, + 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, + 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x6b, 0x65, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, + 0x42, 0xdb, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x42, 0x1c, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x03, 0x50, 0x4b, 0x58, 0xaa, 0x02, 0x12, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x79, 0xca, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4b, 0x61, 0x73, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x1e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5c, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x3a, 0x3a, 0x4b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/namespaces/namespaces.pb.go b/protocol/go/policy/namespaces/namespaces.pb.go index ec14b6d64..cd3d1480c 100644 --- a/protocol/go/policy/namespaces/namespaces.pb.go +++ b/protocol/go/policy/namespaces/namespaces.pb.go @@ -29,7 +29,9 @@ type NamespaceKeyAccessServer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + // Required + NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + // Required KeyAccessServerId string `protobuf:"bytes,2,opt,name=key_access_server_id,json=keyAccessServerId,proto3" json:"key_access_server_id,omitempty"` } @@ -84,6 +86,7 @@ type GetNamespaceRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -178,6 +181,7 @@ type ListNamespacesRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Optional // ACTIVE by default when not specified State common.ActiveStateEnum `protobuf:"varint,1,opt,name=state,proto3,enum=common.ActiveStateEnum" json:"state,omitempty"` } @@ -489,6 +493,7 @@ type DeactivateNamespaceRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -769,109 +774,130 @@ var file_policy_namespaces_namespaces_proto_rawDesc = []byte{ 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, - 0x18, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, - 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22, 0x2d, 0x0a, - 0x13, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x14, - 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x46, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4b, 0x0a, - 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x0a, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x22, 0xfe, 0x04, 0x0a, 0x16, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0xae, 0x04, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x99, 0x04, 0xba, 0x48, 0x95, 0x04, 0xba, 0x01, 0x89, 0x04, 0x0a, - 0x10, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x12, 0xa1, 0x03, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6d, 0x75, - 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x68, 0x6f, - 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, - 0x64, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, - 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x74, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x29, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, - 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, - 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x31, 0x20, 0x74, - 0x6f, 0x20, 0x36, 0x33, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, - 0x6c, 0x6f, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, - 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, - 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, - 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x73, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x74, 0x29, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, - 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, - 0x61, 0x73, 0x74, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, - 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x54, - 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, - 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x51, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, - 0x39, 0x5d, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, - 0x5d, 0x7b, 0x30, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, - 0x39, 0x5d, 0x29, 0x3f, 0x5c, 0x5c, 0x2e, 0x29, 0x2b, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, - 0x5d, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x27, 0x29, 0xc8, 0x01, 0x01, 0x72, 0x03, 0x18, 0xfd, 0x01, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0x4a, 0x0a, 0x17, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, - 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 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, 0x12, - 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, - 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x4a, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x22, 0x34, 0x0a, 0x1a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x44, 0x65, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x95, 0x01, 0x0a, 0x27, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, - 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x96, - 0x01, 0x0a, 0x28, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, + 0x0a, 0x18, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0c, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x14, 0x6b, 0x65, 0x79, 0x5f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, + 0x11, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x49, 0x64, 0x22, 0x2f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x46, 0x0a, 0x15, + 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x22, 0x4b, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, + 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x22, 0xfe, 0x04, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0xae, 0x04, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x99, 0x04, 0xba, 0x48, + 0x95, 0x04, 0xba, 0x01, 0x89, 0x04, 0x0a, 0x10, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xa1, 0x03, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x49, + 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x6f, + 0x74, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x29, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, + 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, + 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, + 0x20, 0x62, 0x65, 0x20, 0x31, 0x20, 0x74, 0x6f, 0x20, 0x36, 0x33, 0x20, 0x63, 0x68, 0x61, 0x72, + 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x62, 0x75, + 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, + 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, + 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, + 0x6c, 0x61, 0x73, 0x74, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x66, 0x74, + 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x74, + 0x29, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x20, 0x6f, + 0x66, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, + 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, + 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, + 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x51, 0x74, 0x68, + 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, 0x5b, 0x61, + 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, + 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x5c, 0x5c, 0x2e, 0x29, 0x2b, + 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x27, 0x29, 0xc8, + 0x01, 0x01, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0x4a, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xbd, + 0x01, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, + 0x02, 0x69, 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, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, + 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x4a, + 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x36, 0x0a, 0x1a, 0x44, 0x65, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x95, 0x01, 0x0a, 0x27, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, + 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x96, 0x01, 0x0a, 0x28, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x22, 0x97, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x6a, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, + 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, + 0x2a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, @@ -879,114 +905,95 @@ var file_policy_namespaces_namespaces_proto_rawDesc = []byte{ 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x97, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x22, 0x98, 0x01, 0x0a, 0x2a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x6a, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x18, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xab, 0x09, 0x0a, - 0x10, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x84, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x26, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, - 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0xab, 0x09, 0x0a, 0x10, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x84, 0x01, 0x0a, + 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x0f, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x90, - 0x01, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, + 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x90, 0x01, 0x0a, 0x0f, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x20, 0x3a, 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0x99, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, - 0x2a, 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xef, 0x01, - 0x0a, 0x20, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x32, + 0x1b, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x99, 0x01, 0x0a, + 0x13, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x2a, 0x1b, 0x2f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xef, 0x01, 0x0a, 0x20, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3a, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x3a, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x4c, 0x3a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x22, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, - 0xd8, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, - 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, - 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x2a, 0x2d, 0x2f, 0x61, 0x74, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4c, 0x3a, 0x1b, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, - 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x42, 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x4e, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0xe2, 0x02, 0x1d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x65, 0x72, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0xd8, 0x01, 0x0a, 0x22, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x12, 0x3c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x3d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x2a, 0x2d, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x6b, + 0x65, 0x79, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x42, + 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, + 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xa2, 0x02, 0x03, + 0x50, 0x4e, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xca, 0x02, 0x11, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0xe2, 0x02, 0x1d, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x12, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/go/policy/objects.pb.go b/protocol/go/policy/objects.pb.go index dc2eb4d8d..6f82b08a0 100644 --- a/protocol/go/policy/objects.pb.go +++ b/protocol/go/policy/objects.pb.go @@ -772,20 +772,6 @@ func (x *SubjectMapping) GetMetadata() *common.Metadata { // * // A Condition defines a rule of -// -// Example: Subjects with a field selected by the flattened selector "'.division'" and a value of "Accounting" or "Marketing": -// { -// "subject_external_selector_value": "'.division'", -// "operator": "SUBJECT_MAPPING_OPERATOR_ENUM_IN", -// "subject_external_values" : ["Accounting", "Marketing"] -// } -// -// Example: Subjects that are not part of the Fantastic Four according to their alias field: -// { -// "subject_external_selector_value": "'.data[0].alias'", -// "operator": "SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN", -// "subject_external_values" : ["mister_fantastic", "the_thing", "human_torch", "invisible_woman"] -// } type Condition struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1250,6 +1236,9 @@ type KeyAccessServer struct { // Address of a KAS instance Uri string `protobuf:"bytes,2,opt,name=uri,proto3" json:"uri,omitempty"` PublicKey *PublicKey `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // Optional + // Unique name of the KAS instance + Name string `protobuf:"bytes,20,opt,name=name,proto3" json:"name,omitempty"` // Common metadata Metadata *common.Metadata `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` } @@ -1307,6 +1296,13 @@ func (x *KeyAccessServer) GetPublicKey() *PublicKey { return nil } +func (x *KeyAccessServer) GetName() string { + if x != nil { + return x.Name + } + return "" +} + func (x *KeyAccessServer) GetMetadata() *common.Metadata { if x != nil { return x.Metadata @@ -1651,68 +1647,69 @@ var file_policy_objects_proto_rawDesc = []byte{ 0x65, 0x74, 0x73, 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, 0x22, 0x80, 0x01, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x15, - 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x29, 0x0a, - 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0xd9, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x02, 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, 0x12, 0x3e, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x06, 0xba, 0x48, - 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x8a, - 0x04, 0x0a, 0x0f, 0x4b, 0x65, 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x86, 0x03, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x42, 0xf3, 0x02, 0xba, 0x48, 0xef, 0x02, 0xba, 0x01, 0xeb, 0x02, 0x0a, 0x0a, 0x75, 0x72, 0x69, - 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xcf, 0x01, 0x55, 0x52, 0x49, 0x20, 0x6d, 0x75, - 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x52, - 0x4c, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x2c, 0x20, 0x27, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, - 0x2f, 0x2f, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x27, 0x29, 0x20, 0x66, 0x6f, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x45, - 0x61, 0x63, 0x68, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, - 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x63, - 0x61, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, - 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, - 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x8a, 0x01, 0x74, 0x68, 0x69, 0x73, - 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x68, 0x74, 0x74, 0x70, 0x73, - 0x3a, 0x2f, 0x2f, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, - 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, 0x2c, - 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, - 0x28, 0x5c, 0x5c, 0x2e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, - 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, - 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, - 0x3f, 0x29, 0x2a, 0x28, 0x3a, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x29, 0x3f, 0x28, 0x2f, 0x2e, - 0x2a, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x30, 0x0a, 0x0a, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, + 0x61, 0x22, 0x7c, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x70, + 0x65, 0x72, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, + 0x9b, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x29, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, + 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0xd9, 0x01, + 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 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, 0x12, + 0x3e, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x0e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x9f, 0x04, 0x0a, 0x0f, 0x4b, 0x65, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x87, 0x03, + 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0xf4, 0x02, 0xba, 0x48, + 0xf0, 0x02, 0xba, 0x01, 0xec, 0x02, 0x0a, 0x0a, 0x75, 0x72, 0x69, 0x5f, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x12, 0xcf, 0x01, 0x55, 0x52, 0x49, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, + 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x28, 0x65, 0x2e, + 0x67, 0x2e, 0x2c, 0x20, 0x27, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x6d, + 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x27, 0x29, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, + 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x73, + 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, + 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, + 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, + 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x8b, 0x01, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3f, 0x3a, 0x2f, 0x2f, 0x5b, + 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, + 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, 0x2c, 0x36, 0x31, 0x7d, 0x5b, + 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x28, 0x5c, 0x5c, 0x2e, + 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x61, 0x2d, 0x7a, + 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, 0x2c, 0x36, 0x31, 0x7d, + 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x29, 0x2a, 0x28, + 0x3a, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x29, 0x3f, 0x28, 0x2f, 0x2e, 0x2a, 0x29, 0x3f, 0x24, + 0x27, 0x29, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x30, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x09, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0x61, 0x0a, 0x0c, 0x4b, diff --git a/protocol/go/policy/resourcemapping/resource_mapping.pb.go b/protocol/go/policy/resourcemapping/resource_mapping.pb.go index 3cc8ad270..131662669 100644 --- a/protocol/go/policy/resourcemapping/resource_mapping.pb.go +++ b/protocol/go/policy/resourcemapping/resource_mapping.pb.go @@ -221,7 +221,8 @@ type CreateResourceMappingGroupRequest struct { // Required NamespaceId string `protobuf:"bytes,1,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Required + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // Common metadata Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` } @@ -335,7 +336,8 @@ type UpdateResourceMappingGroupRequest struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Optional NamespaceId string `protobuf:"bytes,2,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + // Optional + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` // Common metadata Metadata *common.MetadataMutable `protobuf:"bytes,100,opt,name=metadata,proto3" json:"metadata,omitempty"` MetadataUpdateBehavior common.MetadataUpdateEnum `protobuf:"varint,101,opt,name=metadata_update_behavior,json=metadataUpdateBehavior,proto3,enum=common.MetadataUpdateEnum" json:"metadata_update_behavior,omitempty"` @@ -891,42 +893,18 @@ func (x *GetResourceMappingResponse) GetResourceMapping() *policy.ResourceMappin return nil } -// ### Request -// -// grpcurl -plaintext -d @ localhost:8080 policy.resourcemapping.ResourceMappingService/CreateResourceMapping < policy.SubjectProperty - 24, // 1: policy.subjectmapping.MatchSubjectMappingsResponse.subject_mappings:type_name -> policy.SubjectMapping - 24, // 2: policy.subjectmapping.GetSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping - 24, // 3: policy.subjectmapping.ListSubjectMappingsResponse.subject_mappings:type_name -> policy.SubjectMapping - 25, // 4: policy.subjectmapping.CreateSubjectMappingRequest.actions:type_name -> policy.Action + 25, // 0: policy.subjectmapping.MatchSubjectMappingsRequest.subject_properties:type_name -> policy.SubjectProperty + 26, // 1: policy.subjectmapping.MatchSubjectMappingsResponse.subject_mappings:type_name -> policy.SubjectMapping + 26, // 2: policy.subjectmapping.GetSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping + 26, // 3: policy.subjectmapping.ListSubjectMappingsResponse.subject_mappings:type_name -> policy.SubjectMapping + 27, // 4: policy.subjectmapping.CreateSubjectMappingRequest.actions:type_name -> policy.Action 16, // 5: policy.subjectmapping.CreateSubjectMappingRequest.new_subject_condition_set:type_name -> policy.subjectmapping.SubjectConditionSetCreate - 26, // 6: policy.subjectmapping.CreateSubjectMappingRequest.metadata:type_name -> common.MetadataMutable - 24, // 7: policy.subjectmapping.CreateSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping - 25, // 8: policy.subjectmapping.UpdateSubjectMappingRequest.actions:type_name -> policy.Action - 26, // 9: policy.subjectmapping.UpdateSubjectMappingRequest.metadata:type_name -> common.MetadataMutable - 27, // 10: policy.subjectmapping.UpdateSubjectMappingRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 24, // 11: policy.subjectmapping.UpdateSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping - 24, // 12: policy.subjectmapping.DeleteSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping - 28, // 13: policy.subjectmapping.GetSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet - 24, // 14: policy.subjectmapping.GetSubjectConditionSetResponse.associated_subject_mappings:type_name -> policy.SubjectMapping - 28, // 15: policy.subjectmapping.ListSubjectConditionSetsResponse.subject_condition_sets:type_name -> policy.SubjectConditionSet - 29, // 16: policy.subjectmapping.SubjectConditionSetCreate.subject_sets:type_name -> policy.SubjectSet - 26, // 17: policy.subjectmapping.SubjectConditionSetCreate.metadata:type_name -> common.MetadataMutable + 28, // 6: policy.subjectmapping.CreateSubjectMappingRequest.metadata:type_name -> common.MetadataMutable + 26, // 7: policy.subjectmapping.CreateSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping + 27, // 8: policy.subjectmapping.UpdateSubjectMappingRequest.actions:type_name -> policy.Action + 28, // 9: policy.subjectmapping.UpdateSubjectMappingRequest.metadata:type_name -> common.MetadataMutable + 29, // 10: policy.subjectmapping.UpdateSubjectMappingRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 26, // 11: policy.subjectmapping.UpdateSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping + 26, // 12: policy.subjectmapping.DeleteSubjectMappingResponse.subject_mapping:type_name -> policy.SubjectMapping + 30, // 13: policy.subjectmapping.GetSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet + 26, // 14: policy.subjectmapping.GetSubjectConditionSetResponse.associated_subject_mappings:type_name -> policy.SubjectMapping + 30, // 15: policy.subjectmapping.ListSubjectConditionSetsResponse.subject_condition_sets:type_name -> policy.SubjectConditionSet + 31, // 16: policy.subjectmapping.SubjectConditionSetCreate.subject_sets:type_name -> policy.SubjectSet + 28, // 17: policy.subjectmapping.SubjectConditionSetCreate.metadata:type_name -> common.MetadataMutable 16, // 18: policy.subjectmapping.CreateSubjectConditionSetRequest.subject_condition_set:type_name -> policy.subjectmapping.SubjectConditionSetCreate - 28, // 19: policy.subjectmapping.CreateSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet - 29, // 20: policy.subjectmapping.UpdateSubjectConditionSetRequest.subject_sets:type_name -> policy.SubjectSet - 26, // 21: policy.subjectmapping.UpdateSubjectConditionSetRequest.metadata:type_name -> common.MetadataMutable - 27, // 22: policy.subjectmapping.UpdateSubjectConditionSetRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum - 28, // 23: policy.subjectmapping.UpdateSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet - 28, // 24: policy.subjectmapping.DeleteSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet - 0, // 25: policy.subjectmapping.SubjectMappingService.MatchSubjectMappings:input_type -> policy.subjectmapping.MatchSubjectMappingsRequest - 4, // 26: policy.subjectmapping.SubjectMappingService.ListSubjectMappings:input_type -> policy.subjectmapping.ListSubjectMappingsRequest - 2, // 27: policy.subjectmapping.SubjectMappingService.GetSubjectMapping:input_type -> policy.subjectmapping.GetSubjectMappingRequest - 6, // 28: policy.subjectmapping.SubjectMappingService.CreateSubjectMapping:input_type -> policy.subjectmapping.CreateSubjectMappingRequest - 8, // 29: policy.subjectmapping.SubjectMappingService.UpdateSubjectMapping:input_type -> policy.subjectmapping.UpdateSubjectMappingRequest - 10, // 30: policy.subjectmapping.SubjectMappingService.DeleteSubjectMapping:input_type -> policy.subjectmapping.DeleteSubjectMappingRequest - 14, // 31: policy.subjectmapping.SubjectMappingService.ListSubjectConditionSets:input_type -> policy.subjectmapping.ListSubjectConditionSetsRequest - 12, // 32: policy.subjectmapping.SubjectMappingService.GetSubjectConditionSet:input_type -> policy.subjectmapping.GetSubjectConditionSetRequest - 17, // 33: policy.subjectmapping.SubjectMappingService.CreateSubjectConditionSet:input_type -> policy.subjectmapping.CreateSubjectConditionSetRequest - 19, // 34: policy.subjectmapping.SubjectMappingService.UpdateSubjectConditionSet:input_type -> policy.subjectmapping.UpdateSubjectConditionSetRequest - 21, // 35: policy.subjectmapping.SubjectMappingService.DeleteSubjectConditionSet:input_type -> policy.subjectmapping.DeleteSubjectConditionSetRequest - 1, // 36: policy.subjectmapping.SubjectMappingService.MatchSubjectMappings:output_type -> policy.subjectmapping.MatchSubjectMappingsResponse - 5, // 37: policy.subjectmapping.SubjectMappingService.ListSubjectMappings:output_type -> policy.subjectmapping.ListSubjectMappingsResponse - 3, // 38: policy.subjectmapping.SubjectMappingService.GetSubjectMapping:output_type -> policy.subjectmapping.GetSubjectMappingResponse - 7, // 39: policy.subjectmapping.SubjectMappingService.CreateSubjectMapping:output_type -> policy.subjectmapping.CreateSubjectMappingResponse - 9, // 40: policy.subjectmapping.SubjectMappingService.UpdateSubjectMapping:output_type -> policy.subjectmapping.UpdateSubjectMappingResponse - 11, // 41: policy.subjectmapping.SubjectMappingService.DeleteSubjectMapping:output_type -> policy.subjectmapping.DeleteSubjectMappingResponse - 15, // 42: policy.subjectmapping.SubjectMappingService.ListSubjectConditionSets:output_type -> policy.subjectmapping.ListSubjectConditionSetsResponse - 13, // 43: policy.subjectmapping.SubjectMappingService.GetSubjectConditionSet:output_type -> policy.subjectmapping.GetSubjectConditionSetResponse - 18, // 44: policy.subjectmapping.SubjectMappingService.CreateSubjectConditionSet:output_type -> policy.subjectmapping.CreateSubjectConditionSetResponse - 20, // 45: policy.subjectmapping.SubjectMappingService.UpdateSubjectConditionSet:output_type -> policy.subjectmapping.UpdateSubjectConditionSetResponse - 22, // 46: policy.subjectmapping.SubjectMappingService.DeleteSubjectConditionSet:output_type -> policy.subjectmapping.DeleteSubjectConditionSetResponse - 36, // [36:47] is the sub-list for method output_type - 25, // [25:36] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 30, // 19: policy.subjectmapping.CreateSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet + 31, // 20: policy.subjectmapping.UpdateSubjectConditionSetRequest.subject_sets:type_name -> policy.SubjectSet + 28, // 21: policy.subjectmapping.UpdateSubjectConditionSetRequest.metadata:type_name -> common.MetadataMutable + 29, // 22: policy.subjectmapping.UpdateSubjectConditionSetRequest.metadata_update_behavior:type_name -> common.MetadataUpdateEnum + 30, // 23: policy.subjectmapping.UpdateSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet + 30, // 24: policy.subjectmapping.DeleteSubjectConditionSetResponse.subject_condition_set:type_name -> policy.SubjectConditionSet + 30, // 25: policy.subjectmapping.DeleteAllUnmappedSubjectConditionSetsResponse.subject_condition_sets:type_name -> policy.SubjectConditionSet + 0, // 26: policy.subjectmapping.SubjectMappingService.MatchSubjectMappings:input_type -> policy.subjectmapping.MatchSubjectMappingsRequest + 4, // 27: policy.subjectmapping.SubjectMappingService.ListSubjectMappings:input_type -> policy.subjectmapping.ListSubjectMappingsRequest + 2, // 28: policy.subjectmapping.SubjectMappingService.GetSubjectMapping:input_type -> policy.subjectmapping.GetSubjectMappingRequest + 6, // 29: policy.subjectmapping.SubjectMappingService.CreateSubjectMapping:input_type -> policy.subjectmapping.CreateSubjectMappingRequest + 8, // 30: policy.subjectmapping.SubjectMappingService.UpdateSubjectMapping:input_type -> policy.subjectmapping.UpdateSubjectMappingRequest + 10, // 31: policy.subjectmapping.SubjectMappingService.DeleteSubjectMapping:input_type -> policy.subjectmapping.DeleteSubjectMappingRequest + 14, // 32: policy.subjectmapping.SubjectMappingService.ListSubjectConditionSets:input_type -> policy.subjectmapping.ListSubjectConditionSetsRequest + 12, // 33: policy.subjectmapping.SubjectMappingService.GetSubjectConditionSet:input_type -> policy.subjectmapping.GetSubjectConditionSetRequest + 17, // 34: policy.subjectmapping.SubjectMappingService.CreateSubjectConditionSet:input_type -> policy.subjectmapping.CreateSubjectConditionSetRequest + 19, // 35: policy.subjectmapping.SubjectMappingService.UpdateSubjectConditionSet:input_type -> policy.subjectmapping.UpdateSubjectConditionSetRequest + 21, // 36: policy.subjectmapping.SubjectMappingService.DeleteSubjectConditionSet:input_type -> policy.subjectmapping.DeleteSubjectConditionSetRequest + 23, // 37: policy.subjectmapping.SubjectMappingService.DeleteAllUnmappedSubjectConditionSets:input_type -> policy.subjectmapping.DeleteAllUnmappedSubjectConditionSetsRequest + 1, // 38: policy.subjectmapping.SubjectMappingService.MatchSubjectMappings:output_type -> policy.subjectmapping.MatchSubjectMappingsResponse + 5, // 39: policy.subjectmapping.SubjectMappingService.ListSubjectMappings:output_type -> policy.subjectmapping.ListSubjectMappingsResponse + 3, // 40: policy.subjectmapping.SubjectMappingService.GetSubjectMapping:output_type -> policy.subjectmapping.GetSubjectMappingResponse + 7, // 41: policy.subjectmapping.SubjectMappingService.CreateSubjectMapping:output_type -> policy.subjectmapping.CreateSubjectMappingResponse + 9, // 42: policy.subjectmapping.SubjectMappingService.UpdateSubjectMapping:output_type -> policy.subjectmapping.UpdateSubjectMappingResponse + 11, // 43: policy.subjectmapping.SubjectMappingService.DeleteSubjectMapping:output_type -> policy.subjectmapping.DeleteSubjectMappingResponse + 15, // 44: policy.subjectmapping.SubjectMappingService.ListSubjectConditionSets:output_type -> policy.subjectmapping.ListSubjectConditionSetsResponse + 13, // 45: policy.subjectmapping.SubjectMappingService.GetSubjectConditionSet:output_type -> policy.subjectmapping.GetSubjectConditionSetResponse + 18, // 46: policy.subjectmapping.SubjectMappingService.CreateSubjectConditionSet:output_type -> policy.subjectmapping.CreateSubjectConditionSetResponse + 20, // 47: policy.subjectmapping.SubjectMappingService.UpdateSubjectConditionSet:output_type -> policy.subjectmapping.UpdateSubjectConditionSetResponse + 22, // 48: policy.subjectmapping.SubjectMappingService.DeleteSubjectConditionSet:output_type -> policy.subjectmapping.DeleteSubjectConditionSetResponse + 24, // 49: policy.subjectmapping.SubjectMappingService.DeleteAllUnmappedSubjectConditionSets:output_type -> policy.subjectmapping.DeleteAllUnmappedSubjectConditionSetsResponse + 38, // [38:50] is the sub-list for method output_type + 26, // [26:38] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_policy_subjectmapping_subject_mapping_proto_init() } @@ -1937,6 +2075,30 @@ func file_policy_subjectmapping_subject_mapping_proto_init() { return nil } } + file_policy_subjectmapping_subject_mapping_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteAllUnmappedSubjectConditionSetsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_policy_subjectmapping_subject_mapping_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteAllUnmappedSubjectConditionSetsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1944,7 +2106,7 @@ func file_policy_subjectmapping_subject_mapping_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_policy_subjectmapping_subject_mapping_proto_rawDesc, NumEnums: 0, - NumMessages: 23, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, diff --git a/protocol/go/policy/subjectmapping/subject_mapping.pb.gw.go b/protocol/go/policy/subjectmapping/subject_mapping.pb.gw.go index b0c8a2687..aeba060d3 100644 --- a/protocol/go/policy/subjectmapping/subject_mapping.pb.gw.go +++ b/protocol/go/policy/subjectmapping/subject_mapping.pb.gw.go @@ -473,6 +473,24 @@ func local_request_SubjectMappingService_DeleteSubjectConditionSet_0(ctx context } +func request_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0(ctx context.Context, marshaler runtime.Marshaler, client SubjectMappingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq DeleteAllUnmappedSubjectConditionSetsRequest + var metadata runtime.ServerMetadata + + msg, err := client.DeleteAllUnmappedSubjectConditionSets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0(ctx context.Context, marshaler runtime.Marshaler, server SubjectMappingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq DeleteAllUnmappedSubjectConditionSetsRequest + var metadata runtime.ServerMetadata + + msg, err := server.DeleteAllUnmappedSubjectConditionSets(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterSubjectMappingServiceHandlerServer registers the http handlers for service SubjectMappingService to "mux". // UnaryRPC :call SubjectMappingServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -754,6 +772,31 @@ func RegisterSubjectMappingServiceHandlerServer(ctx context.Context, mux *runtim }) + mux.Handle("DELETE", pattern_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/policy.subjectmapping.SubjectMappingService/DeleteAllUnmappedSubjectConditionSets", runtime.WithHTTPPathPattern("/subject-condition-sets/unmapped")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1037,6 +1080,28 @@ func RegisterSubjectMappingServiceHandlerClient(ctx context.Context, mux *runtim }) + mux.Handle("DELETE", pattern_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/policy.subjectmapping.SubjectMappingService/DeleteAllUnmappedSubjectConditionSets", runtime.WithHTTPPathPattern("/subject-condition-sets/unmapped")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1062,6 +1127,8 @@ var ( pattern_SubjectMappingService_UpdateSubjectConditionSet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"subject-condition-sets", "id"}, "")) pattern_SubjectMappingService_DeleteSubjectConditionSet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"subject-condition-sets", "id"}, "")) + + pattern_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"subject-condition-sets", "unmapped"}, "")) ) var ( @@ -1086,4 +1153,6 @@ var ( forward_SubjectMappingService_UpdateSubjectConditionSet_0 = runtime.ForwardResponseMessage forward_SubjectMappingService_DeleteSubjectConditionSet_0 = runtime.ForwardResponseMessage + + forward_SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_0 = runtime.ForwardResponseMessage ) diff --git a/protocol/go/policy/subjectmapping/subject_mapping_grpc.pb.go b/protocol/go/policy/subjectmapping/subject_mapping_grpc.pb.go index 059a1bc00..71a4f6e63 100644 --- a/protocol/go/policy/subjectmapping/subject_mapping_grpc.pb.go +++ b/protocol/go/policy/subjectmapping/subject_mapping_grpc.pb.go @@ -19,17 +19,18 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - SubjectMappingService_MatchSubjectMappings_FullMethodName = "/policy.subjectmapping.SubjectMappingService/MatchSubjectMappings" - SubjectMappingService_ListSubjectMappings_FullMethodName = "/policy.subjectmapping.SubjectMappingService/ListSubjectMappings" - SubjectMappingService_GetSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/GetSubjectMapping" - SubjectMappingService_CreateSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/CreateSubjectMapping" - SubjectMappingService_UpdateSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/UpdateSubjectMapping" - SubjectMappingService_DeleteSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/DeleteSubjectMapping" - SubjectMappingService_ListSubjectConditionSets_FullMethodName = "/policy.subjectmapping.SubjectMappingService/ListSubjectConditionSets" - SubjectMappingService_GetSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/GetSubjectConditionSet" - SubjectMappingService_CreateSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/CreateSubjectConditionSet" - SubjectMappingService_UpdateSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/UpdateSubjectConditionSet" - SubjectMappingService_DeleteSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/DeleteSubjectConditionSet" + SubjectMappingService_MatchSubjectMappings_FullMethodName = "/policy.subjectmapping.SubjectMappingService/MatchSubjectMappings" + SubjectMappingService_ListSubjectMappings_FullMethodName = "/policy.subjectmapping.SubjectMappingService/ListSubjectMappings" + SubjectMappingService_GetSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/GetSubjectMapping" + SubjectMappingService_CreateSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/CreateSubjectMapping" + SubjectMappingService_UpdateSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/UpdateSubjectMapping" + SubjectMappingService_DeleteSubjectMapping_FullMethodName = "/policy.subjectmapping.SubjectMappingService/DeleteSubjectMapping" + SubjectMappingService_ListSubjectConditionSets_FullMethodName = "/policy.subjectmapping.SubjectMappingService/ListSubjectConditionSets" + SubjectMappingService_GetSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/GetSubjectConditionSet" + SubjectMappingService_CreateSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/CreateSubjectConditionSet" + SubjectMappingService_UpdateSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/UpdateSubjectConditionSet" + SubjectMappingService_DeleteSubjectConditionSet_FullMethodName = "/policy.subjectmapping.SubjectMappingService/DeleteSubjectConditionSet" + SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_FullMethodName = "/policy.subjectmapping.SubjectMappingService/DeleteAllUnmappedSubjectConditionSets" ) // SubjectMappingServiceClient is the client API for SubjectMappingService service. @@ -48,6 +49,7 @@ type SubjectMappingServiceClient interface { CreateSubjectConditionSet(ctx context.Context, in *CreateSubjectConditionSetRequest, opts ...grpc.CallOption) (*CreateSubjectConditionSetResponse, error) UpdateSubjectConditionSet(ctx context.Context, in *UpdateSubjectConditionSetRequest, opts ...grpc.CallOption) (*UpdateSubjectConditionSetResponse, error) DeleteSubjectConditionSet(ctx context.Context, in *DeleteSubjectConditionSetRequest, opts ...grpc.CallOption) (*DeleteSubjectConditionSetResponse, error) + DeleteAllUnmappedSubjectConditionSets(ctx context.Context, in *DeleteAllUnmappedSubjectConditionSetsRequest, opts ...grpc.CallOption) (*DeleteAllUnmappedSubjectConditionSetsResponse, error) } type subjectMappingServiceClient struct { @@ -157,6 +159,15 @@ func (c *subjectMappingServiceClient) DeleteSubjectConditionSet(ctx context.Cont return out, nil } +func (c *subjectMappingServiceClient) DeleteAllUnmappedSubjectConditionSets(ctx context.Context, in *DeleteAllUnmappedSubjectConditionSetsRequest, opts ...grpc.CallOption) (*DeleteAllUnmappedSubjectConditionSetsResponse, error) { + out := new(DeleteAllUnmappedSubjectConditionSetsResponse) + err := c.cc.Invoke(ctx, SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // SubjectMappingServiceServer is the server API for SubjectMappingService service. // All implementations must embed UnimplementedSubjectMappingServiceServer // for forward compatibility @@ -173,6 +184,7 @@ type SubjectMappingServiceServer interface { CreateSubjectConditionSet(context.Context, *CreateSubjectConditionSetRequest) (*CreateSubjectConditionSetResponse, error) UpdateSubjectConditionSet(context.Context, *UpdateSubjectConditionSetRequest) (*UpdateSubjectConditionSetResponse, error) DeleteSubjectConditionSet(context.Context, *DeleteSubjectConditionSetRequest) (*DeleteSubjectConditionSetResponse, error) + DeleteAllUnmappedSubjectConditionSets(context.Context, *DeleteAllUnmappedSubjectConditionSetsRequest) (*DeleteAllUnmappedSubjectConditionSetsResponse, error) mustEmbedUnimplementedSubjectMappingServiceServer() } @@ -213,6 +225,9 @@ func (UnimplementedSubjectMappingServiceServer) UpdateSubjectConditionSet(contex func (UnimplementedSubjectMappingServiceServer) DeleteSubjectConditionSet(context.Context, *DeleteSubjectConditionSetRequest) (*DeleteSubjectConditionSetResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteSubjectConditionSet not implemented") } +func (UnimplementedSubjectMappingServiceServer) DeleteAllUnmappedSubjectConditionSets(context.Context, *DeleteAllUnmappedSubjectConditionSetsRequest) (*DeleteAllUnmappedSubjectConditionSetsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteAllUnmappedSubjectConditionSets not implemented") +} func (UnimplementedSubjectMappingServiceServer) mustEmbedUnimplementedSubjectMappingServiceServer() {} // UnsafeSubjectMappingServiceServer may be embedded to opt out of forward compatibility for this service. @@ -424,6 +439,24 @@ func _SubjectMappingService_DeleteSubjectConditionSet_Handler(srv interface{}, c return interceptor(ctx, in, info, handler) } +func _SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteAllUnmappedSubjectConditionSetsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SubjectMappingServiceServer).DeleteAllUnmappedSubjectConditionSets(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SubjectMappingServiceServer).DeleteAllUnmappedSubjectConditionSets(ctx, req.(*DeleteAllUnmappedSubjectConditionSetsRequest)) + } + return interceptor(ctx, in, info, handler) +} + // SubjectMappingService_ServiceDesc is the grpc.ServiceDesc for SubjectMappingService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -475,6 +508,10 @@ var SubjectMappingService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteSubjectConditionSet", Handler: _SubjectMappingService_DeleteSubjectConditionSet_Handler, }, + { + MethodName: "DeleteAllUnmappedSubjectConditionSets", + Handler: _SubjectMappingService_DeleteAllUnmappedSubjectConditionSets_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "policy/subjectmapping/subject_mapping.proto", diff --git a/protocol/go/policy/unsafe/unsafe.pb.go b/protocol/go/policy/unsafe/unsafe.pb.go index 1d8e6ef15..1d1a305b5 100644 --- a/protocol/go/policy/unsafe/unsafe.pb.go +++ b/protocol/go/policy/unsafe/unsafe.pb.go @@ -32,7 +32,8 @@ type UnsafeUpdateNamespaceRequest struct { unknownFields protoimpl.UnknownFields // Required - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Required Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` } @@ -137,6 +138,7 @@ type UnsafeReactivateNamespaceRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -237,6 +239,7 @@ type UnsafeDeleteNamespaceRequest struct { // Required // UUID of the Namespace Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Required // Fully Qualified Name (FQN) of Namespace (i.e. https://), normalized to lower case. Fqn string `protobuf:"bytes,2,opt,name=fqn,proto3" json:"fqn,omitempty"` } @@ -347,9 +350,11 @@ type UnsafeUpdateAttributeRequest struct { // WARNING!! // Updating the name of an Attribute will retroactively alter access to existing TDFs of the old and new Attribute name. Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Optional // WARNING!! // Updating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name. Rule policy.AttributeRuleTypeEnum `protobuf:"varint,3,opt,name=rule,proto3,enum=policy.AttributeRuleTypeEnum" json:"rule,omitempty"` + // Optional // WARNING!! // Unsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition // will retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted @@ -472,6 +477,7 @@ type UnsafeReactivateAttributeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -573,6 +579,7 @@ type UnsafeDeleteAttributeRequest struct { // Required // UUID of the Attribute Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Required // Fully Qualified Name (FQN) of Attribute Definition (i.e. https:///attr/), normalized to lower case. Fqn string `protobuf:"bytes,2,opt,name=fqn,proto3" json:"fqn,omitempty"` } @@ -677,7 +684,9 @@ type UnsafeUpdateAttributeValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Required + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Required Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` } @@ -781,6 +790,7 @@ type UnsafeReactivateAttributeValueRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Required Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } @@ -881,6 +891,7 @@ type UnsafeDeleteAttributeValueRequest struct { // Required // UUID of the Attribute Value Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Required // Fully Qualified Name (FQN) of Attribute Value (i.e. https:///attr//value/), normalized to lower case. Fqn string `protobuf:"bytes,2,opt,name=fqn,proto3" json:"fqn,omitempty"` } @@ -988,277 +999,278 @@ var file_policy_unsafe_unsafe_proto_rawDesc = []byte{ 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe9, 0x04, 0x0a, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x04, 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, - 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xb0, 0x04, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x9b, 0x04, 0xba, 0x48, 0x97, 0x04, 0xba, 0x01, 0x8e, 0x04, 0x0a, - 0x15, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, - 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xa1, 0x03, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x49, 0x74, 0x20, - 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x61, - 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x74, 0x2c, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x20, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x29, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x45, - 0x61, 0x63, 0x68, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, - 0x65, 0x20, 0x31, 0x20, 0x74, 0x6f, 0x20, 0x36, 0x33, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, - 0x74, 0x65, 0x72, 0x73, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, - 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, - 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, - 0x73, 0x74, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x74, 0x29, 0x20, - 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, - 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, - 0x72, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, - 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x51, 0x74, 0x68, 0x69, 0x73, - 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, - 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, - 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, - 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x5c, 0x5c, 0x2e, 0x29, 0x2b, 0x5b, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, - 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, - 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x0a, 0x20, 0x55, 0x6e, - 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, - 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x54, 0x0a, 0x21, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, + 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xb0, 0x04, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9b, 0x04, 0xba, 0x48, 0x97, 0x04, 0xba, 0x01, 0x8e, + 0x04, 0x0a, 0x15, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xa1, 0x03, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x49, + 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x6f, + 0x74, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x29, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, + 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, + 0x20, 0x45, 0x61, 0x63, 0x68, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x6d, 0x75, 0x73, 0x74, + 0x20, 0x62, 0x65, 0x20, 0x31, 0x20, 0x74, 0x6f, 0x20, 0x36, 0x33, 0x20, 0x63, 0x68, 0x61, 0x72, + 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x62, 0x75, + 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, + 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, + 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, + 0x6c, 0x61, 0x73, 0x74, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x66, 0x74, + 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x6f, 0x74, + 0x29, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x20, 0x6f, + 0x66, 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x62, 0x65, 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, + 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, + 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, + 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x51, 0x74, 0x68, + 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, 0x5b, 0x61, + 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x5c, 0x5c, 0x2d, 0x5d, 0x7b, 0x30, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, + 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x5c, 0x5c, 0x2e, 0x29, 0x2b, + 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x32, 0x2c, 0x7d, 0x24, 0x27, 0x29, 0x72, + 0x03, 0x18, 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x50, 0x0a, 0x1c, - 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x22, 0x50, - 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, + 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x3c, 0x0a, 0x20, + 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, + 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x54, 0x0a, 0x21, 0x55, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x22, 0xdd, 0x03, 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xc4, 0x02, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0xaf, 0x02, 0xba, 0x48, 0xab, 0x02, 0xba, - 0x01, 0xa2, 0x02, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb3, 0x01, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, - 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, - 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, - 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, - 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, - 0x1a, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, - 0x20, 0x3f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, - 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, - 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x20, 0x3a, - 0x20, 0x74, 0x72, 0x75, 0x65, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x3b, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x08, 0xba, - 0x48, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x21, 0x0a, - 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x22, 0x3a, 0x0a, 0x20, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x54, - 0x0a, 0x21, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x22, 0x52, 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, + 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x03, 0x66, 0x71, 0x6e, 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xdf, 0x03, 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x61, 0x66, + 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, + 0x64, 0x12, 0xc4, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0xaf, 0x02, 0xba, 0x48, 0xab, 0x02, 0xba, 0x01, 0xa2, 0x02, 0x0a, 0x15, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x12, 0xb3, 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, + 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, + 0x68, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, + 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, + 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, + 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, + 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, + 0x65, 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x53, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, + 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x3f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, + 0x2d, 0x39, 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, + 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x20, 0x3a, 0x20, 0x74, 0x72, 0x75, 0x65, 0x72, 0x03, 0x18, + 0xfd, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x42, 0x08, 0xba, 0x48, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, + 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5f, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, + 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x3c, 0x0a, 0x20, 0x55, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, + 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x54, 0x0a, 0x21, 0x55, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, + 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x52, + 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, + 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x66, + 0x71, 0x6e, 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x22, 0x50, 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, - 0x66, 0x71, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, - 0x01, 0x52, 0x03, 0x66, 0x71, 0x6e, 0x22, 0x50, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0xe5, 0x02, 0x0a, 0x21, 0x55, 0x6e, 0x73, - 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, - 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0xa7, 0x02, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x90, 0x02, 0xba, 0x48, 0x8c, 0x02, 0xba, 0x01, 0x83, - 0x02, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, - 0xb5, 0x01, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, - 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, - 0x65, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, - 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, - 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x20, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, - 0x2d, 0x39, 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, - 0x5f, 0x2d, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, - 0x3f, 0x24, 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x49, 0x0a, 0x22, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3f, 0x0a, 0x25, 0x55, - 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4d, 0x0a, 0x26, + 0x62, 0x75, 0x74, 0x65, 0x22, 0xe7, 0x02, 0x0a, 0x21, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, + 0x52, 0x02, 0x69, 0x64, 0x12, 0xa7, 0x02, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x90, 0x02, 0xba, 0x48, 0x8c, 0x02, 0xba, 0x01, 0x83, 0x02, 0x0a, + 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0xb5, 0x01, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, + 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, + 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, + 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, + 0x63, 0x61, 0x73, 0x65, 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, + 0x5d, 0x28, 0x3f, 0x3a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5f, 0x2d, + 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, + 0x27, 0x29, 0x72, 0x03, 0x18, 0xfd, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x49, + 0x0a, 0x22, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x41, 0x0a, 0x25, 0x55, 0x6e, 0x73, + 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, + 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4d, 0x0a, 0x26, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x55, 0x0a, 0x21, 0x55, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x57, 0x0a, 0x21, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, - 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x66, - 0x71, 0x6e, 0x22, 0x49, 0x0a, 0x22, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0xdc, 0x0b, - 0x0a, 0x0d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x93, 0x01, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, - 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaa, 0x01, 0x0a, 0x19, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, - 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, - 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x22, 0x22, + 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, + 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x03, 0x66, 0x71, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x03, 0x66, 0x71, 0x6e, 0x22, 0x49, 0x0a, 0x22, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, + 0xdc, 0x0b, 0x0a, 0x0d, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x93, 0x01, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x12, 0x93, 0x01, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2b, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, - 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, - 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x93, 0x01, 0x0a, 0x15, 0x55, 0x6e, 0x73, - 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, - 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, - 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaa, - 0x01, 0x0a, 0x19, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, - 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, - 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaa, 0x01, 0x0a, 0x19, 0x55, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, + 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, + 0x22, 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x12, 0x93, 0x01, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2b, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, + 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x19, 0x2a, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x93, 0x01, 0x0a, 0x15, 0x55, + 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, + 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x22, 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, + 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x32, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x93, 0x01, 0x0a, 0x15, - 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, - 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, - 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, - 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0xa9, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, + 0x12, 0xaa, 0x01, 0x0a, 0x19, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2f, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, + 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, + 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x22, 0x22, 0x2f, 0x75, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x93, 0x01, + 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x75, 0x6e, 0x73, + 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0xa9, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x32, 0x1e, 0x2f, - 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xc0, 0x01, - 0x0a, 0x1e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, - 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x29, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x12, 0xa9, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, - 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x32, + 0x1e, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, + 0xc0, 0x01, 0x0a, 0x1e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x34, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, + 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x52, + 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x29, 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, + 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x12, 0xa9, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x30, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x2a, 0x1e, 0x2f, 0x75, - 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xac, 0x01, 0x0a, - 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, 0x61, - 0x66, 0x65, 0x42, 0x0b, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x35, 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, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0xa2, 0x02, 0x03, 0x50, 0x55, 0x58, 0xaa, 0x02, - 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0xca, 0x02, - 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0xe2, 0x02, - 0x19, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, 0x73, + 0x61, 0x66, 0x65, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x2a, 0x1e, + 0x2f, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xac, + 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x75, 0x6e, + 0x73, 0x61, 0x66, 0x65, 0x42, 0x0b, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x35, 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, 0x75, 0x6e, 0x73, 0x61, 0x66, 0x65, 0xa2, 0x02, 0x03, 0x50, 0x55, 0x58, + 0xaa, 0x02, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, + 0xca, 0x02, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, + 0xe2, 0x02, 0x19, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x3a, 0x3a, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 84da888f8..6680b8a80 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.3.17](https://github.com/opentdf/platform/compare/sdk/v0.3.16...sdk/v0.3.17) (2024-10-28) + + +### Bug Fixes + +* **sdk:** option to disable assertion verification ([#1689](https://github.com/opentdf/platform/issues/1689)) ([5c08c47](https://github.com/opentdf/platform/commit/5c08c47d616e98a0dcd2eec4e30a6c04ae71526d)) +* **sdk:** Stops including binding in assertion hashes ([#1681](https://github.com/opentdf/platform/issues/1681)) ([a4583b0](https://github.com/opentdf/platform/commit/a4583b07a15f73027a1a63c619338bf1bdbebe49)) + ## [0.3.16](https://github.com/opentdf/platform/compare/sdk/v0.3.15...sdk/v0.3.16) (2024-10-15) diff --git a/sdk/assertion.go b/sdk/assertion.go index 2447c273a..4191c8440 100644 --- a/sdk/assertion.go +++ b/sdk/assertion.go @@ -28,7 +28,7 @@ type Assertion struct { Scope Scope `json:"scope"` AppliesToState AppliesToState `json:"appliesToState,omitempty"` Statement Statement `json:"statement"` - Binding Binding `json:"binding"` + Binding Binding `json:"binding,omitempty"` } var errAssertionVerifyKeyFailure = errors.New("assertion: failed to verify with provided key") @@ -90,18 +90,34 @@ func (a Assertion) Verify(key AssertionKey) (string, string, error) { // GetHash returns the hash of the assertion in hex format. func (a Assertion) GetHash() ([]byte, error) { - // clear out the binding - a.Binding.Method = "" - a.Binding.Signature = "" + // Clear out the binding + a.Binding = Binding{} + // Marshal the assertion to JSON assertionJSON, err := json.Marshal(a) if err != nil { - return nil, fmt.Errorf("json.Marshal failed:%w", err) + return nil, fmt.Errorf("json.Marshal failed: %w", err) } + // Unmarshal the JSON into a map to manipulate it + var jsonObject map[string]interface{} + if err := json.Unmarshal(assertionJSON, &jsonObject); err != nil { + return nil, fmt.Errorf("json.Unmarshal failed: %w", err) + } + + // Remove the binding key + delete(jsonObject, "binding") + + // Marshal the map back to JSON + assertionJSON, err = json.Marshal(jsonObject) + if err != nil { + return nil, fmt.Errorf("json.Marshal failed: %w", err) + } + + // Transform the JSON using JCS transformedJSON, err := jcs.Transform(assertionJSON) if err != nil { - return nil, fmt.Errorf("jcs.Transform failed:%w", err) + return nil, fmt.Errorf("jcs.Transform failed: %w", err) } return ocrypto.SHA256AsHex(transformedJSON), nil diff --git a/sdk/assertion_test.go b/sdk/assertion_test.go new file mode 100644 index 000000000..f7da55a7c --- /dev/null +++ b/sdk/assertion_test.go @@ -0,0 +1,35 @@ +package sdk + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTDFWithAssertion(t *testing.T) { + assertionConfig := AssertionConfig{ + ID: "424ff3a3-50ca-4f01-a2ae-ef851cd3cac0", + Type: "handling", + Scope: "tdo", + AppliesToState: "encrypted", + Statement: Statement{ + Format: "json+stanag5636", + Schema: "urn:nato:stanag:5636:A:1:elements:json", + Value: "{\"ocl\":{\"pol\":\"62c76c68-d73d-4628-8ccc-4c1e18118c22\",\"cls\":\"SECRET\",\"catl\":[{\"type\":\"P\",\"name\":\"Releasable To\",\"vals\":[\"usa\"]}],\"dcr\":\"2024-10-21T20:47:36Z\"},\"context\":{\"@base\":\"urn:nato:stanag:5636:A:1:elements:json\"}}", + }, + } + + assertion := Assertion{} + + assertion.ID = assertionConfig.ID + assertion.Type = assertionConfig.Type + assertion.Scope = assertionConfig.Scope + assertion.Statement = assertionConfig.Statement + assertion.AppliesToState = assertionConfig.AppliesToState + + hashOfAssertion, err := assertion.GetHash() + require.NoError(t, err) + + assert.Equal(t, "4a447a13c5a32730d20bdf7feecb9ffe16649bc731914b574d80035a3927f860", string(hashOfAssertion)) +} diff --git a/sdk/tdf.go b/sdk/tdf.go index 2655fcb70..5cec00307 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -806,10 +806,10 @@ func (r *Reader) doPayloadKeyUnwrap(ctx context.Context) error { //nolint:gocogn wrappedKey, err = client.unwrap(ctx, keyAccessObj, r.manifest.EncryptionInformation.Policy) if err != nil { errToReturn := fmt.Errorf("doPayloadKeyUnwrap splitKey.rewrap failed: %w", err) - if !strings.Contains(err.Error(), codes.InvalidArgument.String()) { + if strings.Contains(err.Error(), codes.InvalidArgument.String()) { return fmt.Errorf("%w: %w", ErrRewrapBadRequest, errToReturn) } - if !strings.Contains(err.Error(), codes.PermissionDenied.String()) { + if strings.Contains(err.Error(), codes.PermissionDenied.String()) { return fmt.Errorf("%w: %w", errRewrapForbidden, errToReturn) } return errToReturn @@ -904,6 +904,11 @@ func (r *Reader) doPayloadKeyUnwrap(ctx context.Context) error { //nolint:gocogn // Validate assertions for _, assertion := range r.manifest.Assertions { + // Skip assertion verification if disabled + if r.config.disableAssertionVerification { + continue + } + assertionKey := AssertionKey{} // Set default to HS256 assertionKey.Alg = AssertionKeyAlgHS256 diff --git a/sdk/tdf_config.go b/sdk/tdf_config.go index c6b32653b..25f761a85 100644 --- a/sdk/tdf_config.go +++ b/sdk/tdf_config.go @@ -217,11 +217,14 @@ type TDFReaderOption func(*TDFReaderConfig) error type TDFReaderConfig struct { // Optional Map of Assertion Verification Keys - AssertionVerificationKeys AssertionVerificationKeys + AssertionVerificationKeys AssertionVerificationKeys + disableAssertionVerification bool } func newTDFReaderConfig(opt ...TDFReaderOption) (*TDFReaderConfig, error) { - c := &TDFReaderConfig{} + c := &TDFReaderConfig{ + disableAssertionVerification: false, + } for _, o := range opt { err := o(c) if err != nil { @@ -238,3 +241,10 @@ func WithAssertionVerificationKeys(keys AssertionVerificationKeys) TDFReaderOpti return nil } } + +func WithDisableAssertionVerification(disable bool) TDFReaderOption { + return func(c *TDFReaderConfig) error { + c.disableAssertionVerification = disable + return nil + } +} diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index a4ea363d2..dd2bce58d 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -216,9 +216,10 @@ type partialReadTdfTest struct { } type assertionTests struct { - assertions []AssertionConfig - assertionVerificationKeys *AssertionVerificationKeys - expectedSize int + assertions []AssertionConfig + assertionVerificationKeys *AssertionVerificationKeys + disableAssertionVerification bool + expectedSize int } const payload = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" @@ -391,8 +392,9 @@ func (s *TDFSuite) Test_TDFWithAssertion() { }, }, }, - assertionVerificationKeys: nil, - expectedSize: 2896, + assertionVerificationKeys: nil, + disableAssertionVerification: false, + expectedSize: 2896, }, { assertions: []AssertionConfig{ @@ -424,7 +426,8 @@ func (s *TDFSuite) Test_TDFWithAssertion() { assertionVerificationKeys: &AssertionVerificationKeys{ DefaultKey: defaultKey, }, - expectedSize: 2896, + disableAssertionVerification: false, + expectedSize: 2896, }, { assertions: []AssertionConfig{ @@ -472,7 +475,8 @@ func (s *TDFSuite) Test_TDFWithAssertion() { }, }, }, - expectedSize: 3195, + disableAssertionVerification: false, + expectedSize: 3195, }, { assertions: []AssertionConfig{ @@ -511,7 +515,25 @@ func (s *TDFSuite) Test_TDFWithAssertion() { }, }, }, - expectedSize: 2896, + disableAssertionVerification: false, + expectedSize: 2896, + }, + { + assertions: []AssertionConfig{ + { + ID: "assertion2", + Type: BaseAssertion, + Scope: TrustedDataObj, + AppliesToState: Unencrypted, + Statement: Statement{ + Format: "json", + Schema: "urn:nato:stanag:5636:A:1:elements:json", + Value: "{\"uuid\":\"f74efb60-4a9a-11ef-a6f1-8ee1a61c148a\",\"body\":{\"dataAttributes\":null,\"dissem\":null}}", + }, + }, + }, + disableAssertionVerification: true, + expectedSize: 2302, }, } { expectedTdfSize := test.expectedSize @@ -558,9 +580,11 @@ func (s *TDFSuite) Test_TDFWithAssertion() { var r *Reader if test.assertionVerificationKeys == nil { - r, err = s.sdk.LoadTDF(readSeeker) + r, err = s.sdk.LoadTDF(readSeeker, WithDisableAssertionVerification(test.disableAssertionVerification)) } else { - r, err = s.sdk.LoadTDF(readSeeker, WithAssertionVerificationKeys(*test.assertionVerificationKeys)) + r, err = s.sdk.LoadTDF(readSeeker, + WithAssertionVerificationKeys(*test.assertionVerificationKeys), + WithDisableAssertionVerification(test.disableAssertionVerification)) } s.Require().NoError(err) diff --git a/service/CHANGELOG.md b/service/CHANGELOG.md index 280bc3191..b7613a009 100644 --- a/service/CHANGELOG.md +++ b/service/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.4.26](https://github.com/opentdf/platform/compare/service/v0.4.25...service/v0.4.26) (2024-10-17) + + +### Bug Fixes + +* use the right service namespace and update the tests ([#1665](https://github.com/opentdf/platform/issues/1665)) ([72ce62b](https://github.com/opentdf/platform/commit/72ce62b9b79a5b00d9723003789648246dd009b1)) + ## [0.4.25](https://github.com/opentdf/platform/compare/service/v0.4.24...service/v0.4.25) (2024-10-15) diff --git a/service/entityresolution/claims/claims_entity_resolution.go b/service/entityresolution/claims/claims_entity_resolution.go new file mode 100644 index 000000000..cde559cc2 --- /dev/null +++ b/service/entityresolution/claims/claims_entity_resolution.go @@ -0,0 +1,141 @@ +package entityresolution + +import ( + "context" + "fmt" + "log/slog" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/lestrrat-go/jwx/v2/jwt" + "github.com/opentdf/platform/protocol/go/authorization" + "github.com/opentdf/platform/protocol/go/entityresolution" + auth "github.com/opentdf/platform/service/authorization" + "github.com/opentdf/platform/service/logger" + "github.com/opentdf/platform/service/pkg/serviceregistry" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/structpb" +) + +type ClaimsEntityResolutionService struct { + entityresolution.UnimplementedEntityResolutionServiceServer + logger *logger.Logger +} + +func RegisterClaimsERS(_ serviceregistry.ServiceConfig, logger *logger.Logger) (any, serviceregistry.HandlerServer) { + return &ClaimsEntityResolutionService{logger: logger}, + func(ctx context.Context, mux *runtime.ServeMux, server any) error { + return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, server.(entityresolution.EntityResolutionServiceServer)) //nolint:forcetypeassert // allow type assert, following other services + } +} + +func (s ClaimsEntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { + resp, err := EntityResolution(ctx, req, s.logger) + return &resp, err +} + +func (s ClaimsEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { + resp, err := CreateEntityChainFromJwt(ctx, req, s.logger) + return &resp, err +} + +func CreateEntityChainFromJwt( + _ context.Context, + req *entityresolution.CreateEntityChainFromJwtRequest, + _ *logger.Logger, +) (entityresolution.CreateEntityChainFromJwtResponse, error) { + entityChains := []*authorization.EntityChain{} + // for each token in the tokens form an entity chain + for _, tok := range req.GetTokens() { + entities, err := getEntitiesFromToken(tok.GetJwt()) + if err != nil { + return entityresolution.CreateEntityChainFromJwtResponse{}, err + } + entityChains = append(entityChains, &authorization.EntityChain{Id: tok.GetId(), Entities: entities}) + } + + return entityresolution.CreateEntityChainFromJwtResponse{EntityChains: entityChains}, nil +} + +func EntityResolution(_ context.Context, + req *entityresolution.ResolveEntitiesRequest, logger *logger.Logger, +) (entityresolution.ResolveEntitiesResponse, error) { + payload := req.GetEntities() + var resolvedEntities []*entityresolution.EntityRepresentation + + for idx, ident := range payload { + var entityStruct = &structpb.Struct{} + switch ident.GetEntityType().(type) { + case *authorization.Entity_Claims: + claims := ident.GetClaims() + if claims != nil { + err := claims.UnmarshalTo(entityStruct) + if err != nil { + return entityresolution.ResolveEntitiesResponse{}, fmt.Errorf("error unpacking anypb.Any to structpb.Struct: %w", err) + } + } + default: + retrievedStruct, err := entityToStructPb(ident) + if err != nil { + logger.Error("unable to make entity struct", slog.String("error", err.Error())) + return entityresolution.ResolveEntitiesResponse{}, fmt.Errorf("unable to make entity struct: %w", err) + } + entityStruct = retrievedStruct + } + // make sure the id field is populated + originialID := ident.GetId() + if originialID == "" { + originialID = auth.EntityIDPrefix + fmt.Sprint(idx) + } + resolvedEntities = append( + resolvedEntities, + &entityresolution.EntityRepresentation{ + OriginalId: originialID, + AdditionalProps: []*structpb.Struct{entityStruct}, + }, + ) + } + return entityresolution.ResolveEntitiesResponse{EntityRepresentations: resolvedEntities}, nil +} + +func getEntitiesFromToken(jwtString string) ([]*authorization.Entity, error) { + token, err := jwt.ParseString(jwtString, jwt.WithVerify(false), jwt.WithValidate(false)) + if err != nil { + return nil, fmt.Errorf("error parsing jwt: %w", err) + } + + claims := token.PrivateClaims() + entities := []*authorization.Entity{} + + // Convert map[string]interface{} to *structpb.Struct + structClaims, err := structpb.NewStruct(claims) + if err != nil { + return nil, fmt.Errorf("error converting to structpb.Struct: %w", err) + } + + // Wrap the struct in an *anypb.Any message + anyClaims, err := anypb.New(structClaims) + if err != nil { + return nil, fmt.Errorf("error wrapping in anypb.Any: %w", err) + } + + entities = append(entities, &authorization.Entity{ + EntityType: &authorization.Entity_Claims{Claims: anyClaims}, + Id: "jwtentity-claims", + Category: authorization.Entity_CATEGORY_SUBJECT, + }) + return entities, nil +} + +func entityToStructPb(ident *authorization.Entity) (*structpb.Struct, error) { + entityBytes, err := protojson.Marshal(ident) + if err != nil { + return nil, err + } + var entityStruct structpb.Struct + err = entityStruct.UnmarshalJSON(entityBytes) + if err != nil { + return nil, err + } + return &entityStruct, nil +} diff --git a/service/entityresolution/claims/claims_entity_resolution_test.go b/service/entityresolution/claims/claims_entity_resolution_test.go new file mode 100644 index 000000000..3354d8f33 --- /dev/null +++ b/service/entityresolution/claims/claims_entity_resolution_test.go @@ -0,0 +1,125 @@ +package entityresolution_test + +import ( + "context" + "testing" + + "github.com/opentdf/platform/protocol/go/authorization" + "github.com/opentdf/platform/protocol/go/entityresolution" + claims "github.com/opentdf/platform/service/entityresolution/claims" + "github.com/opentdf/platform/service/logger" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/structpb" +) + +const samplejwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImhlbGxvd29ybGQiLCJpYXQiOjE1MTYyMzkwMjJ9.EAOittOMzKENEAs44eaMuZe-xas7VNVsgBxhwmxYiIw" + +func Test_ClientResolveEntity(t *testing.T) { + var validBody []*authorization.Entity + validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_ClientId{ClientId: "random"}}) + + var ctxb = context.Background() + + var req = entityresolution.ResolveEntitiesRequest{} + req.Entities = validBody + + var resp, reserr = claims.EntityResolution(ctxb, &req, logger.CreateTestLogger()) + + require.NoError(t, reserr) + + var entityRepresentations = resp.GetEntityRepresentations() + assert.NotNil(t, entityRepresentations) + assert.Len(t, entityRepresentations, 1) + + assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) + assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) + var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + assert.Equal(t, "random", propMap["clientId"]) + assert.Equal(t, "1234", propMap["id"]) +} + +func Test_EmailResolveEntity(t *testing.T) { + var validBody []*authorization.Entity + validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_EmailAddress{EmailAddress: "random"}}) + + var ctxb = context.Background() + + var req = entityresolution.ResolveEntitiesRequest{} + req.Entities = validBody + + var resp, reserr = claims.EntityResolution(ctxb, &req, logger.CreateTestLogger()) + + require.NoError(t, reserr) + + var entityRepresentations = resp.GetEntityRepresentations() + assert.NotNil(t, entityRepresentations) + assert.Len(t, entityRepresentations, 1) + + assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) + assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) + var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + assert.Equal(t, "random", propMap["emailAddress"]) + assert.Equal(t, "1234", propMap["id"]) +} + +func Test_ClaimsResolveEntity(t *testing.T) { + customclaims := map[string]interface{}{ + "foo": "bar", + "baz": 42, + } + // Convert map[string]interface{} to *structpb.Struct + structClaims, err := structpb.NewStruct(customclaims) + require.NoError(t, err) + + // Wrap the struct in an *anypb.Any + anyClaims, err := anypb.New(structClaims) + require.NoError(t, err) + + var validBody []*authorization.Entity + validBody = append(validBody, &authorization.Entity{Id: "1234", EntityType: &authorization.Entity_Claims{Claims: anyClaims}}) + + var ctxb = context.Background() + + var req = entityresolution.ResolveEntitiesRequest{} + req.Entities = validBody + + var resp, reserr = claims.EntityResolution(ctxb, &req, logger.CreateTestLogger()) + + require.NoError(t, reserr) + + var entityRepresentations = resp.GetEntityRepresentations() + assert.NotNil(t, entityRepresentations) + assert.Len(t, entityRepresentations, 1) + + assert.Equal(t, "1234", entityRepresentations[0].GetOriginalId()) + assert.Len(t, entityRepresentations[0].GetAdditionalProps(), 1) + var propMap = entityRepresentations[0].GetAdditionalProps()[0].AsMap() + assert.Equal(t, "bar", propMap["foo"]) + assert.EqualValues(t, 42, propMap["baz"]) +} + +func Test_JWTToEntityChainClaims(t *testing.T) { + var ctxb = context.Background() + + validBody := []*authorization.Token{{Jwt: samplejwt}} + + var resp, reserr = claims.CreateEntityChainFromJwt(ctxb, &entityresolution.CreateEntityChainFromJwtRequest{Tokens: validBody}, logger.CreateTestLogger()) + + require.NoError(t, reserr) + + assert.Len(t, resp.GetEntityChains(), 1) + assert.Len(t, resp.GetEntityChains()[0].GetEntities(), 1) + assert.IsType(t, &authorization.Entity_Claims{}, resp.GetEntityChains()[0].GetEntities()[0].GetEntityType()) + assert.Equal(t, authorization.Entity_CATEGORY_SUBJECT, resp.GetEntityChains()[0].GetEntities()[0].GetCategory()) + + var unpackedStruct structpb.Struct + err := resp.GetEntityChains()[0].GetEntities()[0].GetClaims().UnmarshalTo(&unpackedStruct) + require.NoError(t, err) + + // Convert structpb.Struct to map[string]interface{} + claimsMap := unpackedStruct.AsMap() + + assert.Equal(t, "helloworld", claimsMap["name"]) +} diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index a539e57f6..9fd6c81e2 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -1,48 +1,36 @@ package entityresolution import ( - "context" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/mitchellh/mapstructure" "github.com/opentdf/platform/protocol/go/entityresolution" + claims "github.com/opentdf/platform/service/entityresolution/claims" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak" - "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/serviceregistry" ) -type EntityResolutionService struct { //nolint:revive // allow for simple naming - entityresolution.UnimplementedEntityResolutionServiceServer - idpConfig keycloak.KeycloakConfig - logger *logger.Logger +type ERSConfig struct { + Mode string `mapstructure:"mode" json:"mode"` } +const KeycloakMode = "keycloak" +const ClaimsMode = "claims" + func NewRegistration() serviceregistry.Registration { return serviceregistry.Registration{ Namespace: "entityresolution", ServiceDesc: &entityresolution.EntityResolutionService_ServiceDesc, RegisterFunc: func(srp serviceregistry.RegistrationParams) (any, serviceregistry.HandlerServer) { - var inputIdpConfig keycloak.KeycloakConfig + var inputConfig ERSConfig - if err := mapstructure.Decode(srp.Config, &inputIdpConfig); err != nil { + if err := mapstructure.Decode(srp.Config, &inputConfig); err != nil { panic(err) } - - srp.Logger.Debug("entity_resolution configuration", "config", inputIdpConfig) - - return &EntityResolutionService{idpConfig: inputIdpConfig, logger: srp.Logger}, func(ctx context.Context, mux *runtime.ServeMux, server any) error { - return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, server.(entityresolution.EntityResolutionServiceServer)) //nolint:forcetypeassert // allow type assert, following other services + if inputConfig.Mode == ClaimsMode { + return claims.RegisterClaimsERS(srp.Config, srp.Logger) } + + // Default to keyclaok ERS + return keycloak.RegisterKeycloakERS(srp.Config, srp.Logger) }, } } - -func (s EntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { - resp, err := keycloak.EntityResolution(ctx, req, s.idpConfig, s.logger) - return &resp, err -} - -func (s EntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { - resp, err := keycloak.CreateEntityChainFromJwt(ctx, req, s.idpConfig, s.logger) - return &resp, err -} diff --git a/service/entityresolution/keycloak/keycloak_entity_resolution.go b/service/entityresolution/keycloak/keycloak_entity_resolution.go index c282e3c7e..a2a9b484c 100644 --- a/service/entityresolution/keycloak/keycloak_entity_resolution.go +++ b/service/entityresolution/keycloak/keycloak_entity_resolution.go @@ -9,11 +9,14 @@ import ( "strings" "github.com/Nerzal/gocloak/v13" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lestrrat-go/jwx/v2/jwt" + "github.com/mitchellh/mapstructure" "github.com/opentdf/platform/protocol/go/authorization" "github.com/opentdf/platform/protocol/go/entityresolution" auth "github.com/opentdf/platform/service/authorization" "github.com/opentdf/platform/service/logger" + "github.com/opentdf/platform/service/pkg/serviceregistry" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" @@ -33,6 +36,12 @@ const ( const serviceAccountUsernamePrefix = "service-account-" +type KeycloakEntityResolutionService struct { + entityresolution.UnimplementedEntityResolutionServiceServer + idpConfig KeycloakConfig + logger *logger.Logger +} + type KeycloakConfig struct { URL string `mapstructure:"url" json:"url"` Realm string `mapstructure:"realm" json:"realm"` @@ -43,6 +52,29 @@ type KeycloakConfig struct { InferID InferredIdentityConfig `mapstructure:"inferid,omitempty" json:"inferid,omitempty"` } +func RegisterKeycloakERS(config serviceregistry.ServiceConfig, logger *logger.Logger) (any, serviceregistry.HandlerServer) { + var inputIdpConfig KeycloakConfig + if err := mapstructure.Decode(config, &inputIdpConfig); err != nil { + panic(err) + } + logger.Debug("entity_resolution configuration", "config", inputIdpConfig) + + return &KeycloakEntityResolutionService{idpConfig: inputIdpConfig, logger: logger}, + func(ctx context.Context, mux *runtime.ServeMux, server any) error { + return entityresolution.RegisterEntityResolutionServiceHandlerServer(ctx, mux, server.(entityresolution.EntityResolutionServiceServer)) //nolint:forcetypeassert // allow type assert, following other services + } +} + +func (s KeycloakEntityResolutionService) ResolveEntities(ctx context.Context, req *entityresolution.ResolveEntitiesRequest) (*entityresolution.ResolveEntitiesResponse, error) { + resp, err := EntityResolution(ctx, req, s.idpConfig, s.logger) + return &resp, err +} + +func (s KeycloakEntityResolutionService) CreateEntityChainFromJwt(ctx context.Context, req *entityresolution.CreateEntityChainFromJwtRequest) (*entityresolution.CreateEntityChainFromJwtResponse, error) { + resp, err := CreateEntityChainFromJwt(ctx, req, s.idpConfig, s.logger) + return &resp, err +} + func (c KeycloakConfig) LogValue() slog.Value { return slog.GroupValue( slog.String("url", c.URL), diff --git a/service/integration/attribute_fqns_test.go b/service/integration/attribute_fqns_test.go index bb63fe7f7..e1c817754 100644 --- a/service/integration/attribute_fqns_test.go +++ b/service/integration/attribute_fqns_test.go @@ -1472,7 +1472,7 @@ func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithNonValueFqns( }) s.Require().Error(err) s.Nil(v) - s.Require().ErrorIs(err, db.ErrFqnMissingValue) + s.Require().ErrorIs(err, db.ErrNotFound) v, err = s.db.PolicyClient.GetAttributesByValueFqns(s.ctx, &attributes.GetAttributeValuesByFqnsRequest{ Fqns: []string{attrFqn}, @@ -1482,5 +1482,5 @@ func (s *AttributeFqnSuite) TestGetAttributesByValueFqns_Fails_WithNonValueFqns( }) s.Require().Error(err) s.Nil(v) - s.Require().ErrorIs(err, db.ErrFqnMissingValue) + s.Require().ErrorIs(err, db.ErrNotFound) } diff --git a/service/integration/namespaces_test.go b/service/integration/namespaces_test.go index 200abc92b..b38bf5cc9 100644 --- a/service/integration/namespaces_test.go +++ b/service/integration/namespaces_test.go @@ -164,9 +164,6 @@ func (s *NamespacesSuite) Test_UpdateNamespace() { }, }) metadata := created.GetMetadata() - // only GET returns populated created/updated times - s.Nil(metadata.GetCreatedAt()) - s.Nil(metadata.GetUpdatedAt()) s.Require().NoError(err) s.NotNil(created) diff --git a/service/integration/subject_mappings_test.go b/service/integration/subject_mappings_test.go index f47fe442d..954dc786a 100644 --- a/service/integration/subject_mappings_test.go +++ b/service/integration/subject_mappings_test.go @@ -17,6 +17,8 @@ type SubjectMappingsSuite struct { suite.Suite f fixtures.Fixtures db fixtures.DBInterface + //nolint:containedctx // Only used for test suite + ctx context.Context } func (s *SubjectMappingsSuite) SetupSuite() { @@ -25,6 +27,7 @@ func (s *SubjectMappingsSuite) SetupSuite() { c.DB.Schema = "test_opentdf_subject_mappings" s.db = fixtures.NewDBInterface(c) s.f = fixtures.NewFixture(s.db) + s.ctx = context.Background() s.f.Provision() } @@ -83,12 +86,12 @@ func (s *SubjectMappingsSuite) TestCreateSubjectMapping_ExistingSubjectCondition Actions: []*policy.Action{aDecrypt, aTransmit}, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) // verify the subject mapping was created - sm, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + sm, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.Equal(newSubjectMapping.GetAttributeValueId(), sm.GetAttributeValue().GetId()) s.Equal(newSubjectMapping.GetExistingSubjectConditionSetId(), sm.GetSubjectConditionSet().GetId()) @@ -125,12 +128,12 @@ func (s *SubjectMappingsSuite) TestCreateSubjectMapping_NewSubjectConditionSet() NewSubjectConditionSet: scs, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) // verify the new subject condition set created was returned properly - sm, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + sm, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(sm.GetSubjectConditionSet()) s.Equal(len(scs.GetSubjectSets()), len(sm.GetSubjectConditionSet().GetSubjectSets())) @@ -156,7 +159,7 @@ func (s *SubjectMappingsSuite) TestCreateSubjectMapping_NonExistentAttributeValu AttributeValueId: nonExistentAttributeValueUUID, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().Error(err) s.Nil(created) s.Require().ErrorIs(err, db.ErrForeignKeyViolation) @@ -171,7 +174,7 @@ func (s *SubjectMappingsSuite) TestCreateSubjectMapping_NonExistentSubjectCondit ExistingSubjectConditionSetId: nonExistentSubjectSetID, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().Error(err) s.Nil(created) s.Require().ErrorIs(err, db.ErrNotFound) @@ -189,7 +192,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_Actions() { Actions: []*policy.Action{aTransmit, aCustomUpload}, ExistingSubjectConditionSetId: fixtureScs.ID, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) @@ -200,13 +203,13 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_Actions() { Actions: newActions, } - updated, err := s.db.PolicyClient.UpdateSubjectMapping(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectMapping(s.ctx, update) s.Require().NoError(err) s.NotNil(updated) s.Equal(created.GetId(), updated.GetId()) // verify the actions were updated but nothing else - got, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(len(newActions), len(got.GetActions())) @@ -233,7 +236,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_SubjectConditionSetId() ExistingSubjectConditionSetId: fixtureScs.ID, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) @@ -244,13 +247,13 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_SubjectConditionSetId() SubjectConditionSetId: newScs.ID, } - updated, err := s.db.PolicyClient.UpdateSubjectMapping(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectMapping(s.ctx, update) s.Require().NoError(err) s.NotNil(updated) s.Equal(created.GetId(), updated.GetId()) // verify the subject condition set was updated but nothing else - got, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(newSubjectMapping.GetAttributeValueId(), got.GetAttributeValue().GetId()) @@ -271,7 +274,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_UpdateAllAllowedFields() ExistingSubjectConditionSetId: fixtureScs.ID, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) @@ -289,13 +292,13 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_UpdateAllAllowedFields() MetadataUpdateBehavior: common.MetadataUpdateEnum_METADATA_UPDATE_ENUM_EXTEND, } - updated, err := s.db.PolicyClient.UpdateSubjectMapping(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectMapping(s.ctx, update) s.Require().NoError(err) s.NotNil(updated) s.Equal(created.GetId(), updated.GetId()) // verify the subject mapping was updated - got, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(created.GetId(), got.GetId()) @@ -315,7 +318,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_NonExistentId_Fails() { MetadataUpdateBehavior: common.MetadataUpdateEnum_METADATA_UPDATE_ENUM_REPLACE, } - sm, err := s.db.PolicyClient.UpdateSubjectMapping(context.Background(), update) + sm, err := s.db.PolicyClient.UpdateSubjectMapping(s.ctx, update) s.Require().Error(err) s.Nil(sm) s.Require().ErrorIs(err, db.ErrNotFound) @@ -327,7 +330,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_NonExistentSubjectCondit SubjectConditionSetId: nonExistentSubjectSetID, } - sm, err := s.db.PolicyClient.UpdateSubjectMapping(context.Background(), update) + sm, err := s.db.PolicyClient.UpdateSubjectMapping(s.ctx, update) s.Require().Error(err) s.Nil(sm) s.Require().ErrorIs(err, db.ErrForeignKeyViolation) @@ -336,7 +339,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectMapping_NonExistentSubjectCondit func (s *SubjectMappingsSuite) TestGetSubjectMapping() { fixture := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute2") - sm, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), fixture.ID) + sm, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, fixture.ID) s.Require().NoError(err) s.NotNil(sm) s.Equal(fixture.ID, sm.GetId()) @@ -355,7 +358,7 @@ func (s *SubjectMappingsSuite) TestGetSubjectMapping() { s.Equal("custom:\""+fixture.Actions[i].Custom+"\"", a.String()) } } - got, err := s.db.PolicyClient.GetAttributeValue(context.Background(), fixture.AttributeValueID) + got, err := s.db.PolicyClient.GetAttributeValue(s.ctx, fixture.AttributeValueID) s.Require().NoError(err) s.NotNil(got) s.Equal(fixture.AttributeValueID, got.GetId()) @@ -367,14 +370,14 @@ func (s *SubjectMappingsSuite) TestGetSubjectMapping() { } func (s *SubjectMappingsSuite) TestGetSubjectMapping_NonExistentId_Fails() { - sm, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), nonExistentSubjectMappingID) + sm, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, nonExistentSubjectMappingID) s.Require().Error(err) s.Nil(sm) s.Require().ErrorIs(err, db.ErrNotFound) } func (s *SubjectMappingsSuite) TestListSubjectMappings() { - list, err := s.db.PolicyClient.ListSubjectMappings(context.Background()) + list, err := s.db.PolicyClient.ListSubjectMappings(s.ctx) s.Require().NoError(err) s.NotNil(list) @@ -423,22 +426,22 @@ func (s *SubjectMappingsSuite) TestDeleteSubjectMapping() { ExistingSubjectConditionSetId: fixtureScs.ID, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) - deleted, err := s.db.PolicyClient.DeleteSubjectMapping(context.Background(), created.GetId()) + deleted, err := s.db.PolicyClient.DeleteSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(deleted) - got, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().Error(err) s.Nil(got) s.Require().ErrorIs(err, db.ErrNotFound) } func (s *SubjectMappingsSuite) TestDeleteSubjectMapping_WithNonExistentId_Fails() { - deleted, err := s.db.PolicyClient.DeleteSubjectMapping(context.Background(), nonExistentSubjectMappingID) + deleted, err := s.db.PolicyClient.DeleteSubjectMapping(s.ctx, nonExistentSubjectMappingID) s.Require().Error(err) s.Nil(deleted) s.Require().ErrorIs(err, db.ErrNotFound) @@ -473,19 +476,19 @@ func (s *SubjectMappingsSuite) TestDeleteSubjectMapping_DoesNotDeleteSubjectCond NewSubjectConditionSet: newScs, } - created, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(created) - sm, err := s.db.PolicyClient.GetSubjectMapping(context.Background(), created.GetId()) + sm, err := s.db.PolicyClient.GetSubjectMapping(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(sm) - deleted, err := s.db.PolicyClient.DeleteSubjectMapping(context.Background(), sm.GetId()) + deleted, err := s.db.PolicyClient.DeleteSubjectMapping(s.ctx, sm.GetId()) s.Require().NoError(err) s.NotNil(deleted) s.NotZero(deleted.GetId()) - scs, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), sm.GetSubjectConditionSet().GetId()) + scs, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, sm.GetSubjectConditionSet().GetId()) s.Require().NoError(err) s.NotNil(scs) s.Equal(sm.GetSubjectConditionSet().GetId(), scs.GetId()) @@ -515,7 +518,7 @@ func (s *SubjectMappingsSuite) TestCreateSubjectConditionSet() { }, } - scs, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), newConditionSet) + scs, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, newConditionSet) s.Require().NoError(err) s.NotNil(scs) } @@ -540,7 +543,7 @@ func (s *SubjectMappingsSuite) TestCreateSubjectConditionSetContains() { }, } - scs, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), newConditionSet) + scs, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, newConditionSet) s.Require().NoError(err) s.NotNil(scs) } @@ -548,7 +551,7 @@ func (s *SubjectMappingsSuite) TestCreateSubjectConditionSetContains() { func (s *SubjectMappingsSuite) TestGetSubjectConditionSet_ById() { fixture := s.f.GetSubjectConditionSetKey("subject_condition_set1") - scs, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), fixture.ID) + scs, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, fixture.ID) s.Require().NoError(err) s.NotNil(scs) s.Equal(fixture.ID, scs.GetId()) @@ -560,21 +563,21 @@ func (s *SubjectMappingsSuite) TestGetSubjectConditionSet_ById() { } func (s *SubjectMappingsSuite) TestGetSubjectConditionSet_WithNoId_Fails() { - scs, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), "") + scs, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, "") s.Require().Error(err) s.Nil(scs) s.Require().ErrorIs(err, db.ErrUUIDInvalid) } func (s *SubjectMappingsSuite) TestGetSubjectConditionSet_NonExistentId_Fails() { - scs, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), nonExistentSubjectSetID) + scs, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, nonExistentSubjectSetID) s.Require().Error(err) s.Nil(scs) s.Require().ErrorIs(err, db.ErrNotFound) } func (s *SubjectMappingsSuite) TestListSubjectConditionSet() { - list, err := s.db.PolicyClient.ListSubjectConditionSets(context.Background()) + list, err := s.db.PolicyClient.ListSubjectConditionSets(s.ctx) s.Require().NoError(err) s.NotNil(list) @@ -612,23 +615,23 @@ func (s *SubjectMappingsSuite) TestDeleteSubjectConditionSet() { SubjectSets: []*policy.SubjectSet{}, } - created, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), newConditionSet) + created, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, newConditionSet) s.Require().NoError(err) s.NotNil(created) - deleted, err := s.db.PolicyClient.DeleteSubjectConditionSet(context.Background(), created.GetId()) + deleted, err := s.db.PolicyClient.DeleteSubjectConditionSet(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(deleted) s.Equal(created.GetId(), deleted.GetId()) - got, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, created.GetId()) s.Require().Error(err) s.Nil(got) s.Require().ErrorIs(err, db.ErrNotFound) } func (s *SubjectMappingsSuite) TestDeleteSubjectConditionSet_WithNonExistentId_Fails() { - deleted, err := s.db.PolicyClient.DeleteSubjectConditionSet(context.Background(), nonExistentSubjectSetID) + deleted, err := s.db.PolicyClient.DeleteSubjectConditionSet(s.ctx, nonExistentSubjectSetID) s.Require().Error(err) s.Nil(deleted) s.Require().ErrorIs(err, db.ErrNotFound) @@ -641,7 +644,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_NewSubjectSets() { {}, }, } - created, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), newConditionSet) + created, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, newConditionSet) s.Require().NoError(err) s.NotNil(created) @@ -669,13 +672,13 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_NewSubjectSets() { MetadataUpdateBehavior: common.MetadataUpdateEnum_METADATA_UPDATE_ENUM_REPLACE, } - updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, update) s.Require().NoError(err) s.NotNil(updated) s.Equal(created.GetId(), updated.GetId()) // verify the subject condition set was updated - got, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(created.GetId(), got.GetId()) @@ -697,7 +700,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_AllAllowedFields() }, } - created, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), newConditionSet) + created, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, newConditionSet) s.Require().NoError(err) s.NotNil(created) @@ -728,13 +731,13 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_AllAllowedFields() Id: created.GetId(), } - updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, update) s.Require().NoError(err) s.NotNil(updated) s.Equal(created.GetId(), updated.GetId()) // verify the subject condition set was updated - got, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(created.GetId(), got.GetId()) @@ -763,7 +766,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_ChangeOperator() { }, } - created, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), newConditionSet) + created, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, newConditionSet) s.Require().NoError(err) s.NotNil(created) @@ -789,11 +792,11 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_ChangeOperator() { SubjectSets: newSS, Id: created.GetId(), } - updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, update) s.Require().NoError(err) s.NotNil(updated) - got, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(created.GetId(), got.GetId()) @@ -810,140 +813,178 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_NonExistentId_Fails SubjectSets: []*policy.SubjectSet{}, } - updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), update) + updated, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, update) s.Require().Error(err) s.Nil(updated) s.Require().ErrorIs(err, db.ErrNotFound) } -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_InOne() { - fixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_set1") - externalSelectorValue := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - externalValues := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalValues - - props := []*policy.SubjectProperty{ - { - ExternalSelectorValue: externalSelectorValue, - ExternalValue: externalValues[0], +func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_SingleMatch() { + externalSelector := ".testing_matched_sm" + fixtureAttrValID := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1").ID + newScs := &subjectmapping.SubjectConditionSetCreate{ + SubjectSets: []*policy.SubjectSet{ + { + ConditionGroups: []*policy.ConditionGroup{ + { + BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, + Conditions: []*policy.Condition{ + { + SubjectExternalSelectorValue: externalSelector, + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{"match"}, + }, + }, + }, + }, + }, }, } + aTransmit := fixtureActions[Transmit] - sm, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + subjectMapping := &subjectmapping.CreateSubjectMappingRequest{ + AttributeValueId: fixtureAttrValID, + Actions: []*policy.Action{aTransmit}, + NewSubjectConditionSet: newScs, + } + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, subjectMapping) s.Require().NoError(err) - s.NotZero(sm) - s.Equal(fixtureScs.ID, sm[0].GetSubjectConditionSet().GetId()) -} - -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_DoesNotReturnNotInWhenMatches() { - fixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_simple_not_in") - externalSelectorValue := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - externalValues := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalValues + s.NotNil(created) props := []*policy.SubjectProperty{ { - ExternalSelectorValue: externalSelectorValue, - ExternalValue: externalValues[0], + ExternalSelectorValue: externalSelector, }, } - smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) s.Require().NoError(err) s.NotZero(smList) - s.Empty(smList) + matched := smList[0] + s.Equal(created.GetId(), matched.GetId()) + s.NotZero(matched.GetAttributeValue().GetId()) + s.NotZero(matched.GetId()) + s.NotNil(matched.GetActions()) } -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_NotInOneMatch() { - fixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_simple_not_in") - externalSelectorValue := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - - expectedMappedFixture := s.f.GetSubjectMappingKey("subject_mapping_subject_simple_not_in") - - props := []*policy.SubjectProperty{ - { - ExternalSelectorValue: externalSelectorValue, - ExternalValue: "random_value", +func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_IgnoresExternalValueInCondition() { + externalSelector := ".testing_unmatched_condition" + fixtureAttrValID := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2").ID + newScs := &subjectmapping.SubjectConditionSetCreate{ + SubjectSets: []*policy.SubjectSet{ + { + ConditionGroups: []*policy.ConditionGroup{ + { + BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, + Conditions: []*policy.Condition{ + { + SubjectExternalSelectorValue: externalSelector, + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{"idp_value"}, + }, + }, + }, + }, + }, }, } + aTransmit := fixtureActions[Transmit] - smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + subjectMapping := &subjectmapping.CreateSubjectMappingRequest{ + AttributeValueId: fixtureAttrValID, + Actions: []*policy.Action{aTransmit}, + NewSubjectConditionSet: newScs, + } + created, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, subjectMapping) s.Require().NoError(err) - s.NotZero(smList) - s.Require().Len(smList, 1) - s.Equal(fixtureScs.ID, smList[0].GetSubjectConditionSet().GetId()) - s.Equal(expectedMappedFixture.ID, smList[0].GetId()) -} + s.NotNil(created) -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_MissingFieldInProperty_Fails() { props := []*policy.SubjectProperty{ { - ExternalValue: "some_value", + ExternalSelectorValue: externalSelector, + ExternalValue: "unrelated", }, } - sm, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) - s.Require().ErrorIs(err, db.ErrMissingValue) - s.Zero(sm) + smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) + s.Require().NoError(err) + s.NotZero(smList) + matched := smList[0] + s.Equal(created.GetId(), matched.GetId()) + s.NotZero(matched.GetAttributeValue().GetId()) + s.NotZero(matched.GetId()) + s.NotNil(matched.GetActions()) } -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_MissingValueInProperty_Fails() { - props := []*policy.SubjectProperty{ - { - ExternalSelectorValue: ".some_field", +func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_MultipleMatches() { + externalSelector1 := ".idp_field" + externalSelector2 := ".org.attributes[]" + // create a two subject mappings with different subject condition sets + fixtureAttrValID := s.f.GetAttributeValueKey("example.com/attr/attr2/value/value2").ID + newScs := &subjectmapping.SubjectConditionSetCreate{ + SubjectSets: []*policy.SubjectSet{ + { + ConditionGroups: []*policy.ConditionGroup{ + { + BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, + Conditions: []*policy.Condition{ + { + SubjectExternalSelectorValue: externalSelector1, + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{"idp_value"}, + }, + }, + }, + }, + }, }, } + aTransmit := fixtureActions[Transmit] - sm, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) - s.Require().ErrorIs(err, db.ErrMissingValue) - s.Zero(sm) -} - -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_NoPropertiesProvided_Fails() { - props := []*policy.SubjectProperty{} + subjectMapping := &subjectmapping.CreateSubjectMappingRequest{ + AttributeValueId: fixtureAttrValID, + Actions: []*policy.Action{aTransmit}, + NewSubjectConditionSet: newScs, + } - sm, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) - s.Require().ErrorIs(err, db.ErrMissingValue) - s.Zero(sm) -} + subjectMappingFirst, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, subjectMapping) + s.Require().NoError(err) + s.NotNil(subjectMappingFirst) -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_InMultiple() { - simpleScs := s.f.GetSubjectConditionSetKey("subject_condition_simple_in") - simpleexternalSelectorValue := simpleScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - simpleExternalValues := simpleScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalValues + // create the second subject mapping with the second SCS + newScs.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue = externalSelector2 + subjectMapping.NewSubjectConditionSet = newScs - otherScs := s.f.GetSubjectConditionSetKey("subject_condition_set1") - otherexternalSelectorValue := otherScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - otherExternalValues := otherScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalValues + subjectMappingSecond, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, subjectMapping) + s.Require().NoError(err) + s.NotNil(subjectMappingSecond) props := []*policy.SubjectProperty{ { - ExternalSelectorValue: simpleexternalSelectorValue, - ExternalValue: simpleExternalValues[0], + ExternalSelectorValue: externalSelector1, }, { - ExternalSelectorValue: otherexternalSelectorValue, - ExternalValue: otherExternalValues[0], + ExternalSelectorValue: externalSelector2, }, } - gotEntitlements, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + candidateEntitlements, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) s.Require().NoError(err) - s.NotZero(gotEntitlements) - s.GreaterOrEqual(len(gotEntitlements), 2) - - mappedSimple := s.f.GetSubjectMappingKey("subject_mapping_subject_simple_in") - foundMappedSimple := false - mappedSubjectConditionSet1 := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute1") - foundMappedSubjectConditionSet1 := false - - for _, sm := range gotEntitlements { - if sm.GetSubjectConditionSet().GetId() == mappedSimple.SubjectConditionSetID { - foundMappedSimple = true - } else if sm.GetSubjectConditionSet().GetId() == mappedSubjectConditionSet1.SubjectConditionSetID { - foundMappedSubjectConditionSet1 = true + s.NotZero(candidateEntitlements) + s.GreaterOrEqual(len(candidateEntitlements), 2) + + foundFirst := false + foundSecond := false + + for _, sm := range candidateEntitlements { + if sm.GetId() == subjectMappingFirst.GetId() { + foundFirst = true + } else if sm.GetId() == subjectMappingSecond.GetId() { + foundSecond = true } } - s.True(foundMappedSimple) - s.True(foundMappedSubjectConditionSet1) + s.True(foundFirst) + s.True(foundSecond) } func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_DeactivatedValueNotReturned() { @@ -957,7 +998,7 @@ func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_DeactivatedValueNot Actions: []*policy.Action{aTransmit}, ExistingSubjectConditionSetId: fixtureScs.ID, } - sm, err := s.db.PolicyClient.CreateSubjectMapping(context.Background(), newSubjectMapping) + sm, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, newSubjectMapping) s.Require().NoError(err) s.NotNil(sm) @@ -965,10 +1006,9 @@ func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_DeactivatedValueNot props := []*policy.SubjectProperty{ { ExternalSelectorValue: fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue, - ExternalValue: fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalValues[0], }, } - smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) s.Require().NoError(err) s.NotZero(smList) @@ -980,80 +1020,133 @@ func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_DeactivatedValueNot } } -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_NotInMultiple() { - fixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_simple_not_in") - externalSelectorValue := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - expectedMappedFixture := s.f.GetSubjectMappingKey("subject_mapping_subject_simple_not_in") - - otherFixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_set3") - otherexternalSelectorValue1 := otherFixtureScs.Condition.SubjectSets[0].ConditionGroups[1].Conditions[1].SubjectExternalSelectorValue - otherExpectedMatchedFixture := s.f.GetSubjectMappingKey("subject_mapping_subject_attribute3") +func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_ConditionSetReusedByMultipleSubjectMappings() { + selector := ".hello_world" + toCreate := &subjectmapping.SubjectConditionSetCreate{ + SubjectSets: []*policy.SubjectSet{ + { + ConditionGroups: []*policy.ConditionGroup{ + { + BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, + Conditions: []*policy.Condition{ + { + SubjectExternalSelectorValue: selector, + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{"goodnight_moon"}, + }, + }, + }, + }, + }, + }, + } + createdSCS, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, toCreate) + s.Require().NoError(err) + s.NotNil(createdSCS) + + // Create two subject mappings across different values that reuse the same subject condition set + attrVal1 := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value1").ID + sm1, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, &subjectmapping.CreateSubjectMappingRequest{ + AttributeValueId: attrVal1, + ExistingSubjectConditionSetId: createdSCS.GetId(), + Actions: []*policy.Action{fixtureActions[Decrypt]}, + }) + s.Require().NoError(err) + s.NotNil(sm1) + attrVal2 := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value2").ID + sm2, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, &subjectmapping.CreateSubjectMappingRequest{ + AttributeValueId: attrVal2, + ExistingSubjectConditionSetId: createdSCS.GetId(), + Actions: []*policy.Action{fixtureActions[Transmit]}, + }) + s.Require().NoError(err) + s.NotNil(sm2) + // check matched subject mappings for the selector in the reused SCS props := []*policy.SubjectProperty{ { - ExternalSelectorValue: externalSelectorValue, - ExternalValue: "random_value_definitely_not_in_fixtures", - }, - { - ExternalSelectorValue: otherexternalSelectorValue1, - ExternalValue: "random_value_definitely_not_in_fixtures", + ExternalSelectorValue: selector, }, } - smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) s.Require().NoError(err) s.NotZero(smList) s.Len(smList, 2) + foundSm1 := false + foundSm2 := false for _, sm := range smList { - if sm.GetSubjectConditionSet().GetId() == fixtureScs.ID { - s.Equal(expectedMappedFixture.ID, sm.GetId()) - } else if sm.GetSubjectConditionSet().GetId() == otherFixtureScs.ID { - s.Equal(otherExpectedMatchedFixture.ID, sm.GetId()) + smID := sm.GetId() + foundSCS := sm.GetSubjectConditionSet().GetId() + foundAttrVal := sm.GetAttributeValue().GetId() + s.Equal(foundSCS, createdSCS.GetId()) + if smID == sm1.GetId() { + foundSm1 = true + s.Equal(sm1.GetAttributeValue().GetId(), foundAttrVal) + } + if smID == sm2.GetId() { + foundSm2 = true + s.Equal(sm2.GetAttributeValue().GetId(), foundAttrVal) } } + s.True(foundSm1) + s.True(foundSm2) } -func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_InOneAndNotInASecond() { - fixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_simple_in") - externalSelectorValue := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - externalValues := fixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalValues - expectedMappedFixture := s.f.GetSubjectMappingKey("subject_mapping_subject_simple_in") +func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_OnlyMatchesOneProperty() { + selector := ".only_matches_one[]" + fixtureAttrValID := s.f.GetAttributeValueKey("example.com/attr/attr1/value/value2").ID + newScs := &subjectmapping.SubjectConditionSetCreate{ + SubjectSets: []*policy.SubjectSet{ + { + ConditionGroups: []*policy.ConditionGroup{ + { + BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, + Conditions: []*policy.Condition{ + { + SubjectExternalSelectorValue: selector, + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{"random_value"}, + }, + }, + }, + }, + }, + }, + } + + subjectMapping := &subjectmapping.CreateSubjectMappingRequest{ + AttributeValueId: fixtureAttrValID, + Actions: []*policy.Action{fixtureActions[Transmit], fixtureActions[Decrypt]}, + NewSubjectConditionSet: newScs, + } - otherFixtureScs := s.f.GetSubjectConditionSetKey("subject_condition_simple_not_in") - otherexternalSelectorValue := otherFixtureScs.Condition.SubjectSets[0].ConditionGroups[0].Conditions[0].SubjectExternalSelectorValue - expectedMappedOtherFixture := s.f.GetSubjectMappingKey("subject_mapping_subject_simple_not_in") + createdSM, err := s.db.PolicyClient.CreateSubjectMapping(s.ctx, subjectMapping) + s.Require().NoError(err) + s.NotNil(createdSM) props := []*policy.SubjectProperty{ { - ExternalSelectorValue: externalSelectorValue, - ExternalValue: externalValues[0], + ExternalSelectorValue: selector, }, { - ExternalSelectorValue: otherexternalSelectorValue, - ExternalValue: "random_value_987654321", + ExternalSelectorValue: "random_value_987654321", }, } - smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + smList, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) s.Require().NoError(err) - s.NotZero(smList) - for _, sm := range smList { - if sm.GetSubjectConditionSet().GetId() == fixtureScs.ID { - s.Equal(expectedMappedFixture.ID, sm.GetId()) - } else if sm.GetSubjectConditionSet().GetId() == otherFixtureScs.ID { - s.Equal(expectedMappedOtherFixture.ID, sm.GetId()) - } - } + s.Len(smList, 1) + s.Equal(smList[0].GetId(), createdSM.GetId()) } func (s *SubjectMappingsSuite) TestGetMatchedSubjectMappings_NonExistentField_ReturnsNoMappings() { props := []*policy.SubjectProperty{ { ExternalSelectorValue: ".non_existent_field[1]", - ExternalValue: "non_existent_value", }, } - sm, err := s.db.PolicyClient.GetMatchedSubjectMappings(context.Background(), props) + sm, err := s.db.PolicyClient.GetMatchedSubjectMappings(s.ctx, props) s.Require().NoError(err) s.NotZero(sm) s.Empty(sm) @@ -1079,7 +1172,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_MetadataVariations( "new": newLabel, } - created, err := s.db.PolicyClient.CreateSubjectConditionSet(context.Background(), &subjectmapping.SubjectConditionSetCreate{ + created, err := s.db.PolicyClient.CreateSubjectConditionSet(s.ctx, &subjectmapping.SubjectConditionSetCreate{ SubjectSets: []*policy.SubjectSet{ {}, }, @@ -1091,7 +1184,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_MetadataVariations( s.NotNil(created) // update with no changes - updatedWithoutChange, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), &subjectmapping.UpdateSubjectConditionSetRequest{ + updatedWithoutChange, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, &subjectmapping.UpdateSubjectConditionSetRequest{ Id: created.GetId(), }) s.Require().NoError(err) @@ -1099,7 +1192,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_MetadataVariations( s.Equal(created.GetId(), updatedWithoutChange.GetId()) // update with changes - updatedWithChange, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), &subjectmapping.UpdateSubjectConditionSetRequest{ + updatedWithChange, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, &subjectmapping.UpdateSubjectConditionSetRequest{ Id: created.GetId(), Metadata: &common.MetadataMutable{Labels: updateLabels}, MetadataUpdateBehavior: common.MetadataUpdateEnum_METADATA_UPDATE_ENUM_EXTEND, @@ -1109,14 +1202,14 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_MetadataVariations( s.Equal(created.GetId(), updatedWithChange.GetId()) // verify the metadata was extended - got, err := s.db.PolicyClient.GetSubjectConditionSet(context.Background(), created.GetId()) + got, err := s.db.PolicyClient.GetSubjectConditionSet(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(created.GetId(), got.GetId()) s.Equal(expectedLabels, got.GetMetadata().GetLabels()) // update with replace - updatedWithReplace, err := s.db.PolicyClient.UpdateSubjectConditionSet(context.Background(), &subjectmapping.UpdateSubjectConditionSetRequest{ + updatedWithReplace, err := s.db.PolicyClient.UpdateSubjectConditionSet(s.ctx, &subjectmapping.UpdateSubjectConditionSetRequest{ Id: created.GetId(), Metadata: &common.MetadataMutable{Labels: labels}, MetadataUpdateBehavior: common.MetadataUpdateEnum_METADATA_UPDATE_ENUM_REPLACE, @@ -1126,7 +1219,7 @@ func (s *SubjectMappingsSuite) TestUpdateSubjectConditionSet_MetadataVariations( s.Equal(created.GetId(), updatedWithReplace.GetId()) // verify the metadata was replaced - got, err = s.db.PolicyClient.GetSubjectConditionSet(context.Background(), created.GetId()) + got, err = s.db.PolicyClient.GetSubjectConditionSet(s.ctx, created.GetId()) s.Require().NoError(err) s.NotNil(got) s.Equal(created.GetId(), got.GetId()) diff --git a/service/internal/auth/casbin.go b/service/internal/auth/casbin.go index bde4b300f..62ff9fd33 100644 --- a/service/internal/auth/casbin.go +++ b/service/internal/auth/casbin.go @@ -89,8 +89,8 @@ p, role:admin, /v1/token/authorization, *, allow p, role:standard, policy.*, read, allow p, role:standard, kasregistry.*, read, allow p, role:standard, kas.AccessService/Rewrap, *, allow -p, role:standard, kas.AuthorizationService/GetDecisions, read, allow -p, role:standard, kas.AuthorizationService/GetDecisionsByToken, read, allow +p, role:standard, authorization.AuthorizationService/GetDecisions, read, allow +p, role:standard, authorization.AuthorizationService/GetDecisionsByToken, read, allow ## HTTP routes p, role:standard, /attributes*, read, allow p, role:standard, /namespaces*, read, allow diff --git a/service/internal/auth/casbin_test.go b/service/internal/auth/casbin_test.go index 5cc58b8a9..2ded15f85 100644 --- a/service/internal/auth/casbin_test.go +++ b/service/internal/auth/casbin_test.go @@ -267,6 +267,18 @@ func (s *AuthnCasbinSuite) Test_Enforcement() { resource: "/kas/v2/rewrap", action: "write", }, + { + allowed: true, + roles: standard, + resource: "authorization.AuthorizationService/GetDecisions", + action: "read", + }, + { + allowed: true, + roles: standard, + resource: "authorization.AuthorizationService/GetDecisionsByToken", + action: "read", + }, // undefined role { diff --git a/service/pkg/db/errors.go b/service/pkg/db/errors.go index 0ca5ec5d2..0299b7a43 100644 --- a/service/pkg/db/errors.go +++ b/service/pkg/db/errors.go @@ -21,7 +21,6 @@ var ( ErrNotFound = errors.New("ErrNotFound: value not found") ErrEnumValueInvalid = errors.New("ErrEnumValueInvalid: not a valid enum value") ErrUUIDInvalid = errors.New("ErrUUIDInvalid: value not a valid UUID") - ErrFqnMissingValue = errors.New("ErrFqnMissingValue: FQN must include a value") ErrMissingValue = errors.New("ErrMissingValue: value must be included") ) @@ -127,10 +126,6 @@ func StatusifyError(err error, fallbackErr string, log ...any) error { slog.Error(ErrTextRestrictViolation, l...) return status.Error(codes.InvalidArgument, ErrTextRestrictViolation) } - if errors.Is(err, ErrFqnMissingValue) { - slog.Error(ErrTextFqnMissingValue, l...) - return status.Error(codes.InvalidArgument, ErrTextFqnMissingValue) - } slog.Error(err.Error(), l...) return status.Error(codes.Internal, fallbackErr) } diff --git a/service/policy/adr/0001-generate-policy-erd.md b/service/policy/adr/0001-generate-policy-erd.md index 17c094681..37a917ac8 100644 --- a/service/policy/adr/0001-generate-policy-erd.md +++ b/service/policy/adr/0001-generate-policy-erd.md @@ -10,7 +10,7 @@ Automation is expected to improve maintenance of an ERD containing the entire sc We will generate a mermaid diagram `.md` schema with a Go tool called [mermerd](https://github.com/KarnerTh/mermerd) that is MIT licensed and actively maintained. -We will place it in `service/policy/db` alongside all DB code and link to it within documentation (see [generated mermerd ERD](../db/policy_erd.md)). +We will place it in `service/policy/db` alongside all DB code and link to it within documentation (see [generated mermerd ERD](../db/schema_erd.md)). At a future time, we may desire to make the following enhancements: diff --git a/service/policy/adr/0002-pagination-list-rpcs.md b/service/policy/adr/0002-pagination-list-rpcs.md new file mode 100644 index 000000000..b26a7b0b0 --- /dev/null +++ b/service/policy/adr/0002-pagination-list-rpcs.md @@ -0,0 +1,177 @@ +# Pagination in policy LIST RPCs + +## Table of Contents + +- [Background](#background) +- [Chosen Option](#chosen-option) +- [Considered Options](#considered-options) + - [LIMIT + OFFSET](#limit--offset) + - [Keyset Pagination](#keyset-pagination) + - [Cursor Pagination](#cursor-pagination) + +## Background + +At present, policy LIST RPCs are completely open-ended. + +Attribute Namespaces, Definitions, and Values LIST calls may be filtered by _active_ state. + +All Policy objects may be retrieved without quantity limits. This presents a challenge at scale if there +are a very large number of any policy object in the platform database when responses become overwhelmingly +large. + +Introduction of a `limit` on retrieved items in LIST procedure call responses necessitates the simultaneous introduction of +pagination. This ADR clarifies the unified approach we will take within policy service LIST RPCs +and at the database level for this pagination. + +## Chosen Option + +[LIMIT + OFFSET](#limit--offset) + +Because we do not know the likelihood of platforms running with Policy where any individual object has +enough rows to experience the at-scale performance concerns of `offset` pagination, we will prefer +this simple implementation for now and leave the door open for cursor-based pagination to solve the performance +constraint should it be a realized problem in the future. + +## Considered Options + +### LIMIT + OFFSET + +The simplest approach is a simple update to the proto for LIST RPCs and db queries to take in `limit` and `offset` with default values. + +```proto +message ListRequest { + // ...existing fields omitted + int32 limit = 3; // default depends on type of policy object + int32 offset = 4; // default: 0 +} +message ListResponse { + // ...existing fields omitted + int32 total = 5; // indication of total available for pagination +} +``` + +```sql +-- subject-mappings example request: +-- 'limit' 100 +-- 'offset' 100 +SELECT * FROM opentdf_policy.subject_mappings +ORDER BY created_at +LIMIT 100 OFFSET 100 +``` + +#### Pros & Cons + +- :green_circle: Simple - support across any SQL database (just slightly different syntax) +- :green_circle: Stateless - each request can independently paginate by specifying LIMIT / OFFSET +- :green_circle: Flexibile - random-access pagination supported +- :green_circle: Familiar - standard across LIST-type APIs +- :yellow_circle: Create/Update/Delete of data between requests may throw off pages, but this is a relatively small concern when reads are exponentially more frequent than writes in Policy +- :red_circle: Performance: large number of objects _or_ a high offset mean a lot of rows need to be scanned and discarded (skipped). However, (:yellow_circle:) we do not know how often the scale of policy objects will be large enough for this to be a problem + +> [!NOTE] +> Pagination is roughly Big O(n) time complexity as offset increases + +### Keyset Pagination + +We would index a column (the most obvious would be `created_at`) to use as the pagination key for +querying, and facilitate pagination before/after any arbitrary timestamp. + +```proto +message ListRequest { + // ...existing fields omitted + int32 limit = 3; // default depends on type of policy object + google.protobuf.Timestamp after = 4; // default: start_of_time + int32 total = 5; // indication of total that can be paginated through +} +message ListResponse { + // ...existing fields omitted + int32 total = 5; // indication of total available for pagination +} +``` + +```sql +-- subject-mappings example request: +-- 'after' 2023-01-01 +-- 'limit' 100 +SELECT * FROM opentdf_policy.subject_mappings +WHERE created_at > '2023-01-01' ORDER BY created_at LIMIT 100; +``` + +#### Pros & Cons + +- :green_circle: Support - supported across any SQL database (just slightly different syntax) +- :green_circle: Speed - much faster in deep pages than OFFSET due to reduced scan row count +- :yellow_circle: Reliability - provisioned policy may contain the same `created_at` timestamp +- :red_circle: Flexibility - pagination is only forward of the `created_at` timestamp +- :red_circle: Complexity - client must maintain state since response timestamps are required to drive subsequent request timestamp pagination, and pagination backwards is not supported +- :red_circle: Complexity - reliance on timestamps introduces timezone differential confusion unless a parameter is also employed to localize the query + +### Cursor Pagination + +We would index a column (the most obvious would be `created_at`) to use as the pagination key for +querying, but we would utilize an encoded cursor approach. + +```proto +message ListRequest { + // ...existing fields omitted + int32 limit = 3; // default depends on type of policy object + string cursor = 4; // defaulted in API layer to cursor for encoded start_of_time +} + +message ListResponse { + // ...existing fields and response data ommitted + // cursors are encoded by the server as base64'd 'created_at' timestamps + string previous_cursor = 4; + string next_cursor = 4; + int32 total = 5; // indication of total available for pagination +} +``` + +```sql +-- subject-mappings example, request: +-- 'after_cursor' 2023-01-01 00:00:00.000000+00 +-- 'limit' 100 +WITH Data AS ( + SELECT * + FROM opentdf_policy.subject_mappings + WHERE created_at >= '2023-01-01 00:00:00.000000+00' + ORDER BY created_at + LIMIT 101 +), +NextPage AS ( + SELECT * + FROM Data + ORDER BY created_at + LIMIT 100 +), +PreviousPage AS ( + SELECT * + FROM opentdf_policy.subject_mappings + WHERE created_at < (SELECT MIN(created_at) FROM Data) + ORDER BY created_at DESC + LIMIT 101 +), +CursorData AS ( + SELECT + (SELECT MIN(created_at) FROM Data) AS first_item_created_at, + (SELECT MAX(created_at) FROM NextPage) AS next_cursor_created_at, + (SELECT MIN(created_at) FROM PreviousPage) AS previous_cursor_created_at +) +SELECT + (SELECT json_agg(row_to_json(NextPage)) FROM NextPage) AS data, + (SELECT json_build_object('created_at', next_cursor_created_at) FROM CursorData) AS next_cursor, + (SELECT json_build_object('created_at', previous_cursor_created_at) FROM CursorData) AS previous_cursor +FROM CursorData; +``` + +#### Pros & Cons + +- :green_circle: Support - supported across any SQL database (just different syntax) +- :green_circle: Speed - much faster in deep pages than OFFSET due to reduced scan row count +- :green_circle: Flexibility - pagination _a single page_ backward made possible by response `previous_cursor` value +- :green_circle: Complexity - timestamp timezone differential is not a problem as cursors are server-determined and an API concern +- :yellow_circle:/:red_circle: Reliability - provisioned policy will sometimes contain the same `created_at` timestamp, making it less than 100% reliable +- :red_circle: New index on the `created_at` timestamp required which adds overhead but little value for management with +time pretty much irrelevant to attributes except if required for sorting +- :red_circle: Complexity - SQL queries become significantly more complex to build and read into responses +- :red_circle: Flexibility - random access is still not supported without client state management and prior knowledge of forward pagination's historical cursors diff --git a/service/policy/adr/0003-database-transactions.md b/service/policy/adr/0003-database-transactions.md new file mode 100644 index 000000000..6a90f7e5b --- /dev/null +++ b/service/policy/adr/0003-database-transactions.md @@ -0,0 +1,81 @@ +# Using Database Transactions in Policy Service + +## Table of Contents + +- [Background](#background) +- [Chosen Option](#chosen-option) +- [Considered Options](#considered-options) + - [LIMIT + OFFSET](#limit--offset) + - [Keyset Pagination](#keyset-pagination) + - [Cursor Pagination](#cursor-pagination) + +## Background + +Due to the complex nature of some operations within the Policy service, we need to consider the use of database transactions to ensure data integrity and consistency. + +## Use Cases + +Primary drivers for implementing database transactions: +- Unsafe operations that update namespace/attribute definition names or attribute values and require FQNs to be updated for consistency +- Attribute defintion creation with multiple attribute values that must be created atomically + +> [!NOTE] +> There are likely to be more as the service matures and more complex operations are required. + +## Implementation + +An abstraction over transactional operations will be introduced to hopefully simplify support for multiple database providers in the future: + +```go +type DbTransaction interface { + Commit(ctx context.Context) error + Rollback(ctx context.Context) +} +``` + +### PolicyDBClient Changes + +New methods for creating transactions and executing operations will be added: + +```go +// Starts a new transaction and returns it +func (c *PolicyDBClient) Begin() (DbTransaction, error) { + // use desired database client to start a new transaction + // - initial implementation will use pgx.Tx with Postgres +} +``` + +```go +// provides a PolicyDBClient instance using the transaction's connection +func (c *PolicyDBClient) WithTx(tx DbTransaction) *PolicyDBClient { + // use desired database client to create a new PolicyDBClient instance with the transaction's connection + // - initial implementation will use pgx.Tx with Postgres +} +``` + +### Usage Example + +It is recommended to create the transaction within the service layer, as calling `WithTx()` from the service layer will inherently provide the transaction to any further `PolicyDBClient` methods called within the DB layer. + +```go +tx, err := dbClient.Begin() +if err != nil { + // handle error +} +defer tx.Rollback(ctx) + +result, err := dbClient.WithTx(tx).SomeOperation(ctx, ...params) +if err != nil { + // handle error +} + +nextResult, err := dbClient.WithTx(tx).AnotherOperation(ctx, ...params) +if err != nil { + // handle error +} + +err = tx.Commit(ctx) +if err != nil { + // handle error +} +``` \ No newline at end of file diff --git a/service/policy/attributes/attributes.proto b/service/policy/attributes/attributes.proto index b95df1aa1..dcbbd9c46 100644 --- a/service/policy/attributes/attributes.proto +++ b/service/policy/attributes/attributes.proto @@ -13,13 +13,25 @@ import "policy/selectors.proto"; */ message AttributeKeyAccessServer { - string attribute_id = 1; - string key_access_server_id = 2; + // Required + string attribute_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required + string key_access_server_id = 2 [ + (buf.validate.field).string.uuid = true + ]; } message ValueKeyAccessServer { - string value_id = 1; - string key_access_server_id = 2; + // Required + string value_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required + string key_access_server_id = 2 [ + (buf.validate.field).string.uuid = true + ]; } /* @@ -27,9 +39,11 @@ message ValueKeyAccessServer { */ message ListAttributesRequest { + // Optional // ACTIVE by default when not specified common.ActiveStateEnum state = 1; - // can be id or name + // Optional + // Namespace ID or name string namespace = 2; } message ListAttributesResponse { @@ -37,7 +51,10 @@ message ListAttributesResponse { } message GetAttributeRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message GetAttributeResponse { policy.Attribute attribute = 1; @@ -45,7 +62,10 @@ message GetAttributeResponse { message CreateAttributeRequest { // Required - string namespace_id = 1 [(buf.validate.field).required = true]; + string namespace_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required string name = 2 [ (buf.validate.field).required = true, (buf.validate.field).string.max_len = 253, @@ -55,11 +75,13 @@ message CreateAttributeRequest { expression: "this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$')" } ]; + // Required AttributeRuleTypeEnum rule = 3 [ (buf.validate.field).enum.defined_only = true, (buf.validate.field).required = true ]; - // Optional attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character. + // Optional + // Attribute values (when provided) must be alphanumeric strings, allowing hyphens and underscores but not as the first or last character. // The stored attribute value will be normalized to lower case. repeated string values = 4 [ (buf.validate.field).repeated = { @@ -84,7 +106,9 @@ message CreateAttributeResponse { message UpdateAttributeRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; // Optional common.MetadataMutable metadata = 100; @@ -95,7 +119,10 @@ message UpdateAttributeResponse { } message DeactivateAttributeRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message DeactivateAttributeResponse { policy.Attribute attribute = 1; @@ -105,14 +132,21 @@ message DeactivateAttributeResponse { /// Value RPC messages /// message GetAttributeValueRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message GetAttributeValueResponse { policy.Value value = 1; } message ListAttributeValuesRequest { - string attribute_id = 1 [(buf.validate.field).required = true]; + // Required + string attribute_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Optional // ACTIVE by default when not specified common.ActiveStateEnum state = 2; } @@ -122,7 +156,10 @@ message ListAttributeValuesResponse { message CreateAttributeValueRequest { // Required - string attribute_id = 1 [(buf.validate.field).required = true]; + string attribute_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required string value = 2 [ (buf.validate.field).required = true, (buf.validate.field).string.max_len = 253, @@ -137,6 +174,7 @@ message CreateAttributeValueRequest { reserved "members"; reserved 3; + // Optional // Common metadata common.MetadataMutable metadata = 100; } @@ -145,12 +183,16 @@ message CreateAttributeValueResponse { } message UpdateAttributeValueRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; // Deprecated reserved "members"; reserved 4; + // Optional // Common metadata common.MetadataMutable metadata = 100; common.MetadataUpdateEnum metadata_update_behavior = 101; @@ -160,7 +202,10 @@ message UpdateAttributeValueResponse { } message DeactivateAttributeValueRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message DeactivateAttributeValueResponse { policy.Value value = 1; @@ -169,8 +214,16 @@ message DeactivateAttributeValueResponse { message GetAttributeValuesByFqnsRequest { // Required // Fully Qualified Names of attribute values (i.e. https:///attr//value/), normalized to lower case. - repeated string fqns = 1 [(buf.validate.field).required = true]; - policy.AttributeValueSelector with_value = 2 [(buf.validate.field).required = true]; + repeated string fqns = 1 [ + (buf.validate.field).repeated = { + min_items: 1, + max_items: 250 + } + ]; + + // Optional + // This attribute value selector is not used currently, but left here for future use. + policy.AttributeValueSelector with_value = 2; } message GetAttributeValuesByFqnsResponse { message AttributeAndValue { @@ -186,6 +239,7 @@ message GetAttributeValuesByFqnsResponse { */ message AssignKeyAccessServerToAttributeRequest { + // Required AttributeKeyAccessServer attribute_key_access_server = 1; } @@ -194,6 +248,7 @@ message AssignKeyAccessServerToAttributeResponse { } message RemoveKeyAccessServerFromAttributeRequest { + // Required AttributeKeyAccessServer attribute_key_access_server = 1; } @@ -202,6 +257,7 @@ message RemoveKeyAccessServerFromAttributeResponse { } message AssignKeyAccessServerToValueRequest { + // Required ValueKeyAccessServer value_key_access_server = 1; } @@ -210,6 +266,7 @@ message AssignKeyAccessServerToValueResponse { } message RemoveKeyAccessServerFromValueRequest { + // Required ValueKeyAccessServer value_key_access_server = 1; } diff --git a/service/policy/attributes/attributes_test.go b/service/policy/attributes/attributes_test.go index 3d233b5a2..7cf1f9d3f 100644 --- a/service/policy/attributes/attributes_test.go +++ b/service/policy/attributes/attributes_test.go @@ -1,6 +1,7 @@ package attributes import ( + "fmt" "strings" "testing" @@ -18,12 +19,16 @@ func getValidator() *protovalidate.Validator { return v } -var ( - validName = "name" - validValue1 = "value1" - validValue2 = "value_2" - validValue3 = "3_value" - validUUID = "00000000-0000-0000-0000-000000000000" +const ( + validName = "name" + validValue1 = "value1" + validValue2 = "value_2" + validValue3 = "3_value" + validUUID = "00000000-0000-0000-0000-000000000000" + errMessageUUID = "string.uuid" + errMessageAttrNameFormat = "attribute_name_format" + errMessageAttrValueFormat = "attribute_value_format" + errMessageRequired = "required" ) // Create Attributes (definitions) @@ -85,7 +90,7 @@ func TestCreateAttribute_NameWithSpace_Fails(t *testing.T) { err := v.Validate(req) require.Error(t, err) - require.Contains(t, err.Error(), "[attribute_name_format]") + require.Contains(t, err.Error(), errMessageAttrNameFormat) } func TestCreateAttribute_NameWithNonAlphanumeric_Fails(t *testing.T) { @@ -106,7 +111,7 @@ func TestCreateAttribute_NameWithNonAlphanumeric_Fails(t *testing.T) { err := v.Validate(req) require.Error(t, err) - require.Contains(t, err.Error(), "[attribute_name_format]") + require.Contains(t, err.Error(), errMessageAttrNameFormat) } } @@ -121,7 +126,7 @@ func TestCreateAttribute_NamespaceIdMissing_Fails(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "namespace_id") - require.Contains(t, err.Error(), "[required]") + require.Contains(t, err.Error(), errMessageUUID) } func TestCreateAttribute_RuleMissing_Fails(t *testing.T) { @@ -135,7 +140,7 @@ func TestCreateAttribute_RuleMissing_Fails(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "rule") - require.Contains(t, err.Error(), "[required]") + require.Contains(t, err.Error(), errMessageRequired) } func TestCreateAttribute_RuleUnspecified_Fails(t *testing.T) { @@ -150,7 +155,7 @@ func TestCreateAttribute_RuleUnspecified_Fails(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "rule") - require.Contains(t, err.Error(), "[required]") + require.Contains(t, err.Error(), errMessageRequired) } func TestCreateAttribute_RuleInvalid_Fails(t *testing.T) { @@ -187,6 +192,86 @@ func TestCreateAttribute_ValueInvalid_Fails(t *testing.T) { require.Contains(t, err.Error(), "[string.pattern]") } +func TestAttributeKeyAccessServer_Succeeds(t *testing.T) { + validAttrKAS := &attributes.AttributeKeyAccessServer{ + AttributeId: validUUID, + KeyAccessServerId: validUUID, + } + + err := getValidator().Validate(validAttrKAS) + require.NoError(t, err) +} + +func TestAttributeKeyAccessServer_Fails(t *testing.T) { + bad := []struct { + attrID string + kasID string + }{ + { + "", + validUUID, + }, + { + validUUID, + "", + }, + { + "", + "", + }, + {}, + } + + for _, test := range bad { + invalidAttrKAS := &attributes.AttributeKeyAccessServer{ + AttributeId: test.attrID, + KeyAccessServerId: test.kasID, + } + err := getValidator().Validate(invalidAttrKAS) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + } +} + +func TestGetAttributeRequest(t *testing.T) { + req := &attributes.GetAttributeRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.GetAttributeRequest{ + Id: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + +func TestUpdateAttributeRequest(t *testing.T) { + req := &attributes.UpdateAttributeRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.UpdateAttributeRequest{ + Id: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + +func TestDeactivateAttributeRequest(t *testing.T) { + req := &attributes.DeactivateAttributeRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.DeactivateAttributeRequest{ + Id: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + // Create Attribute Values func TestCreateAttributeValue_Valid_Succeeds(t *testing.T) { @@ -225,7 +310,7 @@ func TestCreateAttributeValue_ValueWithSpace_Fails(t *testing.T) { err := v.Validate(req) require.Error(t, err) - require.Contains(t, err.Error(), "[attribute_value_format]") + require.Contains(t, err.Error(), errMessageAttrValueFormat) } func TestCreateAttributeValue_ValueWithNonAlphanumeric_Fails(t *testing.T) { @@ -245,7 +330,7 @@ func TestCreateAttributeValue_ValueWithNonAlphanumeric_Fails(t *testing.T) { err := v.Validate(req) require.Error(t, err) - require.Contains(t, err.Error(), "[attribute_value_format]") + require.Contains(t, err.Error(), errMessageAttrValueFormat) } } @@ -259,7 +344,7 @@ func TestCreateAttributeValue_AttributeIdMissing_Fails(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "attribute_id") - require.Contains(t, err.Error(), "[required]") + require.Contains(t, err.Error(), errMessageUUID) } func TestCreateAttributeValue_ValueMissing_Fails(t *testing.T) { @@ -272,5 +357,154 @@ func TestCreateAttributeValue_ValueMissing_Fails(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "value") - require.Contains(t, err.Error(), "[required]") + require.Contains(t, err.Error(), errMessageRequired) +} + +func TestValueKeyAccessServer_Succeeds(t *testing.T) { + validValueKAS := &attributes.ValueKeyAccessServer{ + ValueId: validUUID, + KeyAccessServerId: validUUID, + } + + err := getValidator().Validate(validValueKAS) + require.NoError(t, err) +} + +func TestValueKeyAccessServer_Fails(t *testing.T) { + bad := []struct { + valID string + kasID string + }{ + { + "", + validUUID, + }, + { + validUUID, + "", + }, + { + "", + "", + }, + {}, + } + + for _, test := range bad { + invalidValKAS := &attributes.ValueKeyAccessServer{ + ValueId: test.valID, + KeyAccessServerId: test.kasID, + } + err := getValidator().Validate(invalidValKAS) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + } +} + +func TestGetAttributeValueRequest(t *testing.T) { + req := &attributes.GetAttributeValueRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.GetAttributeValueRequest{ + Id: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + +func TestListAttributeValuesRequest(t *testing.T) { + req := &attributes.ListAttributeValuesRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.ListAttributeValuesRequest{ + AttributeId: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + +func TestUpdateAttributeValueRequest(t *testing.T) { + req := &attributes.UpdateAttributeValueRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.UpdateAttributeValueRequest{ + Id: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + +func TestDeactivateAttributeValueRequest(t *testing.T) { + req := &attributes.DeactivateAttributeValueRequest{} + err := getValidator().Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req = &attributes.DeactivateAttributeValueRequest{ + Id: validUUID, + } + err = getValidator().Validate(req) + require.NoError(t, err) +} + +func TestGetAttributeValuesByFqns_Valid_Succeeds(t *testing.T) { + req := &attributes.GetAttributeValuesByFqnsRequest{ + Fqns: []string{ + "any_value", + }, + } + + v := getValidator() + err := v.Validate(req) + + require.NoError(t, err) +} + +func TestGetAttributeValuesByFqns_FQNsNil_Fails(t *testing.T) { + req := &attributes.GetAttributeValuesByFqnsRequest{} + + v := getValidator() + err := v.Validate(req) + + require.Error(t, err) + require.Contains(t, err.Error(), "fqns") + require.Contains(t, err.Error(), "[repeated.min_items]") +} + +func TestGetAttributeValuesByFqns_FQNsEmpty_Fails(t *testing.T) { + req := &attributes.GetAttributeValuesByFqnsRequest{ + Fqns: []string{}, + } + + v := getValidator() + err := v.Validate(req) + + require.Error(t, err) + require.Contains(t, err.Error(), "fqns") + require.Contains(t, err.Error(), "[repeated.min_items]") +} + +func TestGetAttributeValuesByFqns_FQNsOutsideMaxItemsRange_Fails(t *testing.T) { + outsideRange := 251 + fqns := make([]string, outsideRange) + for i := 0; i < outsideRange; i++ { + fqns[i] = fmt.Sprintf("fqn_%d", i) + } + + req := &attributes.GetAttributeValuesByFqnsRequest{ + Fqns: fqns, + } + + v := getValidator() + err := v.Validate(req) + + require.Error(t, err) + require.Contains(t, err.Error(), "fqns") + require.Contains(t, err.Error(), "[repeated.max_items]") } diff --git a/service/policy/db/README.md b/service/policy/db/README.md index fa0f70d16..ea2cbc578 100644 --- a/service/policy/db/README.md +++ b/service/policy/db/README.md @@ -36,6 +36,8 @@ Other useful subcommands also exist on `sqlc`, like `vet`, `compile`, `verify`, ### Schema ERD +[Current schema](./schema_erd.md) + The schema in the policy database is managed through `Goose` migrations (see above), which are also read into the `sqlc` generated code to execute db queries within Go. diff --git a/service/policy/db/attribute_fqn.go b/service/policy/db/attribute_fqn.go index e7e59442b..30a5eeb8a 100644 --- a/service/policy/db/attribute_fqn.go +++ b/service/policy/db/attribute_fqn.go @@ -2,59 +2,13 @@ package db import ( "context" - "errors" "fmt" - "log/slog" "strings" "github.com/opentdf/platform/protocol/go/policy/attributes" "github.com/opentdf/platform/service/pkg/db" ) -// These values are optional, but at least one must be set. The other values will be derived from -// the set values. -type attrFqnUpsertOptions struct { - namespaceID string - attributeID string - valueID string -} - -// This logic is a bit complex. What we are trying to achieve is to upsert the fqn based on the -// combination of namespaceId, attributeId, and valueId. However, instead of requiring all three -// we want to support partial attribute FQNs. This means that we need to support the following -// combinations: -// 1. namespaceId -// 2. namespaceId, attributeId -// 3. namespaceId, attributeId, valueId -// -// This is a side effect -- errors will be swallowed and the fqn will be returned as an empty string -func (c *PolicyDBClient) upsertAttrFqn(ctx context.Context, opts attrFqnUpsertOptions) string { - var ( - fqn string - err error - ) - - switch { - case opts.valueID != "": - fqn, err = c.Queries.UpsertAttributeValueFqn(ctx, opts.valueID) - case opts.attributeID != "": - fqn, err = c.Queries.UpsertAttributeDefinitionFqn(ctx, opts.attributeID) - case opts.namespaceID != "": - fqn, err = c.Queries.UpsertAttributeNamespaceFqn(ctx, opts.namespaceID) - default: - err = fmt.Errorf("at least one of namespaceId, attributeId, or valueId must be set") - } - - if err != nil { - wrappedErr := db.WrapIfKnownInvalidQueryErr(err) - c.logger.ErrorContext(ctx, "could not update FQN", slog.Any("opts", opts), slog.String("error", wrappedErr.Error())) - return "" - } - - c.logger.DebugContext(ctx, "updated FQN", slog.String("fqn", fqn), slog.Any("opts", opts)) - return fqn -} - // AttrFqnReindex will reindex all namespace, attribute, and attribute_value FQNs func (c *PolicyDBClient) AttrFqnReindex(ctx context.Context) (res struct { //nolint:nonamedreturns // Used to initialize an anonymous struct Namespaces []struct { @@ -77,40 +31,37 @@ func (c *PolicyDBClient) AttrFqnReindex(ctx context.Context) (res struct { //nol panic(fmt.Errorf("could not get namespaces: %w", err)) } - // Get all attributes - attrs, err := c.ListAllAttributes(ctx) - if err != nil { - panic(fmt.Errorf("could not get attributes: %w", err)) - } - - // Get all attribute values - values, err := c.ListAllAttributeValues(ctx) - if err != nil { - panic(fmt.Errorf("could not get attribute values: %w", err)) - } - // Reindex all namespaces + reindexedRecords := []UpsertAttributeNamespaceFqnRow{} for _, n := range ns { - res.Namespaces = append(res.Namespaces, struct { - ID string - Fqn string - }{ID: n.GetId(), Fqn: c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: n.GetId()})}) - } - - // Reindex all attributes - for _, a := range attrs { - res.Attributes = append(res.Attributes, struct { - ID string - Fqn string - }{ID: a.GetId(), Fqn: c.upsertAttrFqn(ctx, attrFqnUpsertOptions{attributeID: a.GetId()})}) - } - - // Reindex all attribute values - for _, av := range values { - res.Values = append(res.Values, struct { - ID string - Fqn string - }{ID: av.GetId(), Fqn: c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueID: av.GetId()})}) + rows, err := c.Queries.UpsertAttributeNamespaceFqn(ctx, n.GetId()) + if err != nil { + panic(fmt.Errorf("could not update namespace [%s] FQN: %w", n.GetId(), err)) + } + reindexedRecords = append(reindexedRecords, rows...) + } + + for _, r := range reindexedRecords { + switch { + case r.AttributeID == "" && r.ValueID == "": + // namespace record + res.Namespaces = append(res.Namespaces, struct { + ID string + Fqn string + }{ID: r.NamespaceID, Fqn: r.Fqn}) + case r.ValueID == "": + // attribute definition record + res.Attributes = append(res.Attributes, struct { + ID string + Fqn string + }{ID: r.AttributeID, Fqn: r.Fqn}) + default: + // attribute value record + res.Values = append(res.Values, struct { + ID string + Fqn string + }{ID: r.ValueID, Fqn: r.Fqn}) + } } return res @@ -119,23 +70,12 @@ func (c *PolicyDBClient) AttrFqnReindex(ctx context.Context) (res struct { //nol func (c *PolicyDBClient) GetAttributesByValueFqns(ctx context.Context, r *attributes.GetAttributeValuesByFqnsRequest) (map[string]*attributes.GetAttributeValuesByFqnsResponse_AttributeAndValue, error) { fqns := r.GetFqns() - // todo: move to proto validation - if fqns == nil || r.GetWithValue() == nil { - return nil, errors.Join(db.ErrMissingValue, errors.New("error: one or more FQNs and a WithValue selector must be provided")) - } - list := make(map[string]*attributes.GetAttributeValuesByFqnsResponse_AttributeAndValue, len(fqns)) for i, fqn := range fqns { // normalize to lower case fqn = strings.ToLower(fqn) - // ensure the FQN corresponds to an attribute value and not a definition or namespace alone - // todo: move to proto validation - if !strings.Contains(fqn, "/value/") { - return nil, db.ErrFqnMissingValue - } - // update array with normalized FQN fqns[i] = fqn diff --git a/service/policy/db/attribute_values.go b/service/policy/db/attribute_values.go index 0cad42a1c..5cddd269d 100644 --- a/service/policy/db/attribute_values.go +++ b/service/policy/db/attribute_values.go @@ -18,7 +18,7 @@ import ( func (c PolicyDBClient) CreateAttributeValue(ctx context.Context, attributeID string, r *attributes.CreateAttributeValueRequest) (*policy.Value, error) { value := strings.ToLower(r.GetValue()) - metadataJSON, metadata, err := db.MarshalCreateMetadata(r.GetMetadata()) + metadataJSON, _, err := db.MarshalCreateMetadata(r.GetMetadata()) if err != nil { return nil, err } @@ -33,23 +33,12 @@ func (c PolicyDBClient) CreateAttributeValue(ctx context.Context, attributeID st } // Update FQN - fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueID: createdID}) - if fqn != "" { - c.logger.Debug("created new attribute value FQN", - slog.String("value_id", createdID), - slog.String("value", value), - slog.String("fqn", fqn), - ) + _, err = c.Queries.UpsertAttributeValueFqn(ctx, createdID) + if err != nil { + return nil, db.WrapIfKnownInvalidQueryErr(err) } - return &policy.Value{ - Id: createdID, - Attribute: &policy.Attribute{Id: attributeID}, - Value: value, - Metadata: metadata, - Active: &wrapperspb.BoolValue{Value: true}, - Fqn: fqn, - }, nil + return c.GetAttributeValue(ctx, createdID) } func (c PolicyDBClient) GetAttributeValue(ctx context.Context, id string) (*policy.Value, error) { @@ -176,18 +165,12 @@ func (c PolicyDBClient) UnsafeUpdateAttributeValue(ctx context.Context, r *unsaf } // Update FQN - fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{valueID: id}) - c.logger.Debug("upserted fqn for unsafely updated value", - slog.String("id", id), - slog.String("value", value), - slog.String("fqn", fqn), - ) + _, err = c.Queries.UpsertAttributeValueFqn(ctx, id) + if err != nil { + return nil, db.WrapIfKnownInvalidQueryErr(err) + } - return &policy.Value{ - Id: id, - Value: value, - Fqn: fqn, - }, nil + return c.GetAttributeValue(ctx, id) } func (c PolicyDBClient) DeactivateAttributeValue(ctx context.Context, id string) (*policy.Value, error) { diff --git a/service/policy/db/attributes.go b/service/policy/db/attributes.go index f72204d85..acf3f2e59 100644 --- a/service/policy/db/attributes.go +++ b/service/policy/db/attributes.go @@ -5,7 +5,6 @@ import ( "database/sql" "encoding/json" "fmt" - "log/slog" "strings" "github.com/google/uuid" @@ -282,7 +281,7 @@ func (c PolicyDBClient) GetAttributesByNamespace(ctx context.Context, namespaceI func (c PolicyDBClient) CreateAttribute(ctx context.Context, r *attributes.CreateAttributeRequest) (*policy.Attribute, error) { name := strings.ToLower(r.GetName()) namespaceID := r.GetNamespaceId() - metadataJSON, metadata, err := db.MarshalCreateMetadata(r.GetMetadata()) + metadataJSON, _, err := db.MarshalCreateMetadata(r.GetMetadata()) if err != nil { return nil, err } @@ -299,48 +298,24 @@ func (c PolicyDBClient) CreateAttribute(ctx context.Context, r *attributes.Creat } // Add values - var values []*policy.Value for _, v := range r.GetValues() { req := &attributes.CreateAttributeValueRequest{ AttributeId: createdID, Value: v, } - value, err := c.CreateAttributeValue(ctx, createdID, req) + _, err := c.CreateAttributeValue(ctx, createdID, req) if err != nil { return nil, err } - values = append(values, value) } // Update the FQNs - fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{ - namespaceID: namespaceID, - attributeID: createdID, - }) - c.logger.DebugContext(ctx, "upserted fqn with new attribute definition", slog.Any("fqn", fqn)) - - for _, v := range values { - fqn = c.upsertAttrFqn(ctx, attrFqnUpsertOptions{ - namespaceID: namespaceID, - attributeID: createdID, - valueID: v.GetId(), - }) - c.logger.DebugContext(ctx, "upserted fqn with new attribute value on new definition create", slog.Any("fqn", fqn)) + _, err = c.Queries.UpsertAttributeDefinitionFqn(ctx, createdID) + if err != nil { + return nil, db.WrapIfKnownInvalidQueryErr(err) } - a := &policy.Attribute{ - Id: createdID, - Name: name, - Rule: r.GetRule(), - Metadata: metadata, - Namespace: &policy.Namespace{ - Id: namespaceID, - }, - Active: &wrapperspb.BoolValue{Value: true}, - Values: values, - Fqn: fqn, - } - return a, nil + return c.GetAttribute(ctx, createdID) } func (c PolicyDBClient) UnsafeUpdateAttribute(ctx context.Context, r *unsafe.UnsafeUpdateAttributeRequest) (*policy.Attribute, error) { @@ -396,27 +371,15 @@ func (c PolicyDBClient) UnsafeUpdateAttribute(ctx context.Context, r *unsafe.Uns return nil, db.ErrNotFound } - attribute := &policy.Attribute{ - Id: id, - Name: name, - Rule: rule, - } - // Upsert all the FQNs with the definition name mutation if name != "" { - namespaceID := before.GetNamespace().GetId() - attrFqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: namespaceID, attributeID: id}) - c.logger.Debug("upserted attribute fqn with new definition name", slog.Any("fqn", attrFqn)) - if len(before.GetValues()) > 0 { - for _, v := range before.GetValues() { - fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: namespaceID, attributeID: id, valueID: v.GetId()}) - c.logger.Debug("upserted attribute value fqn with new definition name", slog.Any("fqn", fqn)) - } + _, err = c.Queries.UpsertAttributeDefinitionFqn(ctx, id) + if err != nil { + return nil, db.WrapIfKnownInvalidQueryErr(err) } - attribute.Fqn = attrFqn } - return attribute, nil + return c.GetAttribute(ctx, id) } func (c PolicyDBClient) UpdateAttribute(ctx context.Context, id string, r *attributes.UpdateAttributeRequest) (*policy.Attribute, error) { diff --git a/service/policy/db/db.go b/service/policy/db/db.go index 5b8c8f530..b4a3b78a3 100644 --- a/service/policy/db/db.go +++ b/service/policy/db/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 package db diff --git a/service/policy/db/migrations/20241014000000_add_kas_name_to_registry.md b/service/policy/db/migrations/20241014000000_add_kas_name_to_registry.md new file mode 100644 index 000000000..60d81fab8 --- /dev/null +++ b/service/policy/db/migrations/20241014000000_add_kas_name_to_registry.md @@ -0,0 +1,14 @@ +# Add KAS Name to Registry + +```mermaid + +erDiagram + + KeyAccessServer { + uuid id PK + varchar uri UK + varchar name UK "new optional name column" + jsonb public_key + jsonb metadata + } +``` diff --git a/service/policy/db/migrations/20241014000000_add_kas_name_to_registry.sql b/service/policy/db/migrations/20241014000000_add_kas_name_to_registry.sql new file mode 100644 index 000000000..9769a5fa3 --- /dev/null +++ b/service/policy/db/migrations/20241014000000_add_kas_name_to_registry.sql @@ -0,0 +1,19 @@ +-- +goose Up +-- +goose StatementBegin + +ALTER TABLE IF EXISTS key_access_servers + ADD COLUMN IF NOT EXISTS name VARCHAR UNIQUE; + +COMMENT ON COLUMN key_access_servers.name IS 'Optional common name of the KAS'; + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +COMMENT ON COLUMN key_access_servers.name IS NULL; + +ALTER TABLE IF EXISTS key_access_servers + DROP COLUMN IF EXISTS name; + +-- +goose StatementEnd diff --git a/service/policy/db/models.go b/service/policy/db/models.go index 8d0c94ee0..b3f5ddcb1 100644 --- a/service/policy/db/models.go +++ b/service/policy/db/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 package db diff --git a/service/policy/db/namespaces.go b/service/policy/db/namespaces.go index d86bb5d40..d1fd0a0c2 100644 --- a/service/policy/db/namespaces.go +++ b/service/policy/db/namespaces.go @@ -80,7 +80,7 @@ func (c PolicyDBClient) ListNamespaces(ctx context.Context, state string) ([]*po func (c PolicyDBClient) CreateNamespace(ctx context.Context, r *namespaces.CreateNamespaceRequest) (*policy.Namespace, error) { name := strings.ToLower(r.GetName()) - metadataJSON, metadata, err := db.MarshalCreateMetadata(r.GetMetadata()) + metadataJSON, _, err := db.MarshalCreateMetadata(r.GetMetadata()) if err != nil { return nil, err } @@ -94,16 +94,12 @@ func (c PolicyDBClient) CreateNamespace(ctx context.Context, r *namespaces.Creat } // Update FQN - fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: createdID}) - c.logger.Debug("upserted fqn for created namespace", slog.Any("fqn", fqn)) + _, err = c.Queries.UpsertAttributeNamespaceFqn(ctx, createdID) + if err != nil { + return nil, db.WrapIfKnownInvalidQueryErr(err) + } - return &policy.Namespace{ - Id: createdID, - Name: name, - Active: &wrapperspb.BoolValue{Value: true}, - Metadata: metadata, - Fqn: fqn, - }, nil + return c.GetNamespace(ctx, createdID) } func (c PolicyDBClient) UpdateNamespace(ctx context.Context, id string, r *namespaces.UpdateNamespaceRequest) (*policy.Namespace, error) { @@ -157,27 +153,12 @@ func (c PolicyDBClient) UnsafeUpdateNamespace(ctx context.Context, id string, na } // Update all FQNs that may contain the namespace name - nsFqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id}) - c.logger.Debug("upserted fqn for unsafely updated namespace", slog.Any("fqn", nsFqn)) - - attrs, err := c.ListAttributes(ctx, StateAny, id) + _, err = c.Queries.UpsertAttributeNamespaceFqn(ctx, id) if err != nil { - return nil, err - } - for _, attr := range attrs { - fqn := c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id, attributeID: attr.GetId()}) - c.logger.Debug("upserted definition fqn for unsafely updated namespace", slog.Any("fqn", fqn)) - for _, value := range attr.GetValues() { - fqn = c.upsertAttrFqn(ctx, attrFqnUpsertOptions{namespaceID: id, attributeID: attr.GetId(), valueID: value.GetId()}) - c.logger.Debug("upserted value fqn for unsafely updated namespace", slog.Any("fqn", fqn)) - } + return nil, db.WrapIfKnownInvalidQueryErr(err) } - return &policy.Namespace{ - Id: id, - Name: name, - Fqn: nsFqn, - }, nil + return c.GetNamespace(ctx, id) } func (c PolicyDBClient) DeactivateNamespace(ctx context.Context, id string) (*policy.Namespace, error) { diff --git a/service/policy/db/policy.go b/service/policy/db/policy.go index 2f8eface0..5889f9398 100644 --- a/service/policy/db/policy.go +++ b/service/policy/db/policy.go @@ -34,45 +34,7 @@ func (c *PolicyDBClient) WithTx(tx pgx.Tx) *PolicyDBClient { return &PolicyDBClient{c.Client, c.logger, c.Queries.WithTx(tx)} } -var ( - TableAttributes = "attribute_definitions" - TableAttributeValues = "attribute_values" - TableNamespaces = "attribute_namespaces" - TableAttrFqn = "attribute_fqns" - TableAttributeKeyAccessGrants = "attribute_definition_key_access_grants" - TableAttributeValueKeyAccessGrants = "attribute_value_key_access_grants" - TableResourceMappings = "resource_mappings" - TableSubjectMappings = "subject_mappings" - TableSubjectConditionSet = "subject_condition_set" - TableKeyAccessServerRegistry = "key_access_servers" -) - -var Tables struct { - Attributes db.Table - AttributeValues db.Table - Namespaces db.Table - AttrFqn db.Table - AttributeKeyAccessGrants db.Table - AttributeValueKeyAccessGrants db.Table - ResourceMappings db.Table - SubjectMappings db.Table - SubjectConditionSet db.Table - KeyAccessServerRegistry db.Table -} - func NewClient(c *db.Client, logger *logger.Logger) PolicyDBClient { - t := db.NewTable(c.Schema()) - Tables.Attributes = t(TableAttributes) - Tables.AttributeValues = t(TableAttributeValues) - Tables.Namespaces = t(TableNamespaces) - Tables.AttrFqn = t(TableAttrFqn) - Tables.AttributeKeyAccessGrants = t(TableAttributeKeyAccessGrants) - Tables.AttributeValueKeyAccessGrants = t(TableAttributeValueKeyAccessGrants) - Tables.ResourceMappings = t(TableResourceMappings) - Tables.SubjectMappings = t(TableSubjectMappings) - Tables.SubjectConditionSet = t(TableSubjectConditionSet) - Tables.KeyAccessServerRegistry = t(TableKeyAccessServerRegistry) - return PolicyDBClient{c, logger, New(c.Pgx)} } diff --git a/service/policy/db/query.sql b/service/policy/db/query.sql index 5efd5819a..364582ae9 100644 --- a/service/policy/db/query.sql +++ b/service/policy/db/query.sql @@ -82,50 +82,121 @@ DELETE FROM key_access_servers WHERE id = $1; -- ATTRIBUTE FQN ---------------------------------------------------------------- --- name: UpsertAttributeValueFqn :one +-- name: UpsertAttributeValueFqn :many +WITH new_fqns_cte AS ( + -- get attribute value fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + av.id as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn + FROM attribute_values av + JOIN attribute_definitions ad on av.attribute_definition_id = ad.id + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE av.id = @value_id +) INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) -SELECT - n.id, - ad.id, - av.id, - CONCAT('https://', n.name, '/attr/', ad.name, '/value/', av.value) AS fqn -FROM attribute_namespaces n -JOIN attribute_definitions ad ON n.id = ad.namespace_id -JOIN attribute_values av ON ad.id = av.attribute_definition_id -WHERE av.id = $1 +SELECT + namespace_id, + attribute_id, + value_id, + fqn +FROM new_fqns_cte ON CONFLICT (namespace_id, attribute_id, value_id) DO UPDATE SET fqn = EXCLUDED.fqn -RETURNING fqn; - --- name: UpsertAttributeDefinitionFqn :one +RETURNING + COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, + COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, + COALESCE(value_id::TEXT, '')::TEXT as value_id, + fqn; + +-- name: UpsertAttributeDefinitionFqn :many +WITH new_fqns_cte AS ( + -- get attribute definition fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + NULL::UUID as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name) AS fqn + FROM attribute_definitions ad + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ad.id = @attribute_id + UNION + -- get attribute value fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + av.id as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn + FROM attribute_values av + JOIN attribute_definitions ad on av.attribute_definition_id = ad.id + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ad.id = @attribute_id +) INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) -SELECT - n.id, - ad.id, - NULL, - CONCAT('https://', n.name, '/attr/', ad.name) AS fqn -FROM attribute_namespaces n -JOIN attribute_definitions ad ON n.id = ad.namespace_id -WHERE ad.id = $1 +SELECT + namespace_id, + attribute_id, + value_id, + fqn +FROM new_fqns_cte ON CONFLICT (namespace_id, attribute_id, value_id) DO UPDATE SET fqn = EXCLUDED.fqn -RETURNING fqn; - --- name: UpsertAttributeNamespaceFqn :one +RETURNING + COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, + COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, + COALESCE(value_id::TEXT, '')::TEXT as value_id, + fqn; + +-- name: UpsertAttributeNamespaceFqn :many +WITH new_fqns_cte AS ( + -- get namespace fqns + SELECT + ns.id as namespace_id, + NULL::UUID as attribute_id, + NULL::UUID as value_id, + CONCAT('https://', ns.name) AS fqn + FROM attribute_namespaces ns + WHERE ns.id = @namespace_id + UNION + -- get attribute definition fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + NULL::UUID as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name) AS fqn + FROM attribute_definitions ad + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ns.id = @namespace_id + UNION + -- get attribute value fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + av.id as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn + FROM attribute_values av + JOIN attribute_definitions ad on av.attribute_definition_id = ad.id + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ns.id = @namespace_id +) INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) -SELECT - n.id, - NULL, - NULL, - CONCAT('https://', n.name) AS fqn -FROM attribute_namespaces n -WHERE n.id = $1 +SELECT + namespace_id, + attribute_id, + value_id, + fqn +FROM new_fqns_cte ON CONFLICT (namespace_id, attribute_id, value_id) DO UPDATE SET fqn = EXCLUDED.fqn -RETURNING fqn; +RETURNING + COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, + COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, + COALESCE(value_id::TEXT, '')::TEXT as value_id, + fqn; ---------------------------------------------------------------- -- ATTRIBUTES @@ -691,6 +762,28 @@ LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id WHERE sm.id = $1 GROUP BY av.id, sm.id, scs.id; +-- name: MatchSubjectMappings :many +SELECT + sm.id, + sm.actions, + JSON_BUILD_OBJECT( + 'id', scs.id, + 'subject_sets', scs.condition + ) AS subject_condition_set, + JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value +FROM subject_mappings sm +LEFT JOIN attribute_values av ON sm.attribute_value_id = av.id +LEFT JOIN attribute_definitions ad ON av.attribute_definition_id = ad.id +LEFT JOIN attribute_namespaces ns ON ad.namespace_id = ns.id +LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id +WHERE ns.active = true AND ad.active = true and av.active = true AND EXISTS ( + SELECT 1 + FROM JSONB_ARRAY_ELEMENTS(scs.condition) AS ss, JSONB_ARRAY_ELEMENTS(ss->'conditionGroups') AS cg, JSONB_ARRAY_ELEMENTS(cg->'conditions') AS each_condition + WHERE (each_condition->>'subjectExternalSelectorValue' = ANY(@selectors::TEXT[])) +) +GROUP BY av.id, sm.id, scs.id; + + -- name: CreateSubjectMapping :one INSERT INTO subject_mappings (attribute_value_id, actions, metadata, subject_condition_set_id) VALUES ($1, $2, $3, $4) diff --git a/service/policy/db/query.sql.go b/service/policy/db/query.sql.go index 9e708f210..9dc32a918 100644 --- a/service/policy/db/query.sql.go +++ b/service/policy/db/query.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 // source: query.sql package db @@ -1999,6 +1999,81 @@ func (q *Queries) ListSubjectMappings(ctx context.Context) ([]ListSubjectMapping return items, nil } +const matchSubjectMappings = `-- name: MatchSubjectMappings :many +SELECT + sm.id, + sm.actions, + JSON_BUILD_OBJECT( + 'id', scs.id, + 'subject_sets', scs.condition + ) AS subject_condition_set, + JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value +FROM subject_mappings sm +LEFT JOIN attribute_values av ON sm.attribute_value_id = av.id +LEFT JOIN attribute_definitions ad ON av.attribute_definition_id = ad.id +LEFT JOIN attribute_namespaces ns ON ad.namespace_id = ns.id +LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id +WHERE ns.active = true AND ad.active = true and av.active = true AND EXISTS ( + SELECT 1 + FROM JSONB_ARRAY_ELEMENTS(scs.condition) AS ss, JSONB_ARRAY_ELEMENTS(ss->'conditionGroups') AS cg, JSONB_ARRAY_ELEMENTS(cg->'conditions') AS each_condition + WHERE (each_condition->>'subjectExternalSelectorValue' = ANY($1::TEXT[])) +) +GROUP BY av.id, sm.id, scs.id +` + +type MatchSubjectMappingsRow struct { + ID string `json:"id"` + Actions []byte `json:"actions"` + SubjectConditionSet []byte `json:"subject_condition_set"` + AttributeValue []byte `json:"attribute_value"` +} + +// MatchSubjectMappings +// +// SELECT +// sm.id, +// sm.actions, +// JSON_BUILD_OBJECT( +// 'id', scs.id, +// 'subject_sets', scs.condition +// ) AS subject_condition_set, +// JSON_BUILD_OBJECT('id', av.id,'value', av.value,'active', av.active) AS attribute_value +// FROM subject_mappings sm +// LEFT JOIN attribute_values av ON sm.attribute_value_id = av.id +// LEFT JOIN attribute_definitions ad ON av.attribute_definition_id = ad.id +// LEFT JOIN attribute_namespaces ns ON ad.namespace_id = ns.id +// LEFT JOIN subject_condition_set scs ON scs.id = sm.subject_condition_set_id +// WHERE ns.active = true AND ad.active = true and av.active = true AND EXISTS ( +// SELECT 1 +// FROM JSONB_ARRAY_ELEMENTS(scs.condition) AS ss, JSONB_ARRAY_ELEMENTS(ss->'conditionGroups') AS cg, JSONB_ARRAY_ELEMENTS(cg->'conditions') AS each_condition +// WHERE (each_condition->>'subjectExternalSelectorValue' = ANY($1::TEXT[])) +// ) +// GROUP BY av.id, sm.id, scs.id +func (q *Queries) MatchSubjectMappings(ctx context.Context, selectors []string) ([]MatchSubjectMappingsRow, error) { + rows, err := q.db.Query(ctx, matchSubjectMappings, selectors) + if err != nil { + return nil, err + } + defer rows.Close() + var items []MatchSubjectMappingsRow + for rows.Next() { + var i MatchSubjectMappingsRow + if err := rows.Scan( + &i.ID, + &i.Actions, + &i.SubjectConditionSet, + &i.AttributeValue, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const removeKeyAccessServerFromAttribute = `-- name: RemoveKeyAccessServerFromAttribute :execrows DELETE FROM attribute_definition_key_access_grants WHERE attribute_definition_id = $1 AND key_access_server_id = $2 @@ -2365,119 +2440,336 @@ func (q *Queries) UpdateSubjectMapping(ctx context.Context, arg UpdateSubjectMap return result.RowsAffected(), nil } -const upsertAttributeDefinitionFqn = `-- name: UpsertAttributeDefinitionFqn :one +const upsertAttributeDefinitionFqn = `-- name: UpsertAttributeDefinitionFqn :many +WITH new_fqns_cte AS ( + -- get attribute definition fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + NULL::UUID as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name) AS fqn + FROM attribute_definitions ad + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ad.id = $1 + UNION + -- get attribute value fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + av.id as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn + FROM attribute_values av + JOIN attribute_definitions ad on av.attribute_definition_id = ad.id + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ad.id = $1 +) INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) -SELECT - n.id, - ad.id, - NULL, - CONCAT('https://', n.name, '/attr/', ad.name) AS fqn -FROM attribute_namespaces n -JOIN attribute_definitions ad ON n.id = ad.namespace_id -WHERE ad.id = $1 +SELECT + namespace_id, + attribute_id, + value_id, + fqn +FROM new_fqns_cte ON CONFLICT (namespace_id, attribute_id, value_id) DO UPDATE SET fqn = EXCLUDED.fqn -RETURNING fqn +RETURNING + COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, + COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, + COALESCE(value_id::TEXT, '')::TEXT as value_id, + fqn ` +type UpsertAttributeDefinitionFqnRow struct { + NamespaceID string `json:"namespace_id"` + AttributeID string `json:"attribute_id"` + ValueID string `json:"value_id"` + Fqn string `json:"fqn"` +} + // UpsertAttributeDefinitionFqn // +// WITH new_fqns_cte AS ( +// -- get attribute definition fqns +// SELECT +// ns.id as namespace_id, +// ad.id as attribute_id, +// NULL::UUID as value_id, +// CONCAT('https://', ns.name, '/attr/', ad.name) AS fqn +// FROM attribute_definitions ad +// JOIN attribute_namespaces ns on ad.namespace_id = ns.id +// WHERE ad.id = $1 +// UNION +// -- get attribute value fqns +// SELECT +// ns.id as namespace_id, +// ad.id as attribute_id, +// av.id as value_id, +// CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn +// FROM attribute_values av +// JOIN attribute_definitions ad on av.attribute_definition_id = ad.id +// JOIN attribute_namespaces ns on ad.namespace_id = ns.id +// WHERE ad.id = $1 +// ) // INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) // SELECT -// n.id, -// ad.id, -// NULL, -// CONCAT('https://', n.name, '/attr/', ad.name) AS fqn -// FROM attribute_namespaces n -// JOIN attribute_definitions ad ON n.id = ad.namespace_id -// WHERE ad.id = $1 +// namespace_id, +// attribute_id, +// value_id, +// fqn +// FROM new_fqns_cte // ON CONFLICT (namespace_id, attribute_id, value_id) // DO UPDATE // SET fqn = EXCLUDED.fqn -// RETURNING fqn -func (q *Queries) UpsertAttributeDefinitionFqn(ctx context.Context, id string) (string, error) { - row := q.db.QueryRow(ctx, upsertAttributeDefinitionFqn, id) - var fqn string - err := row.Scan(&fqn) - return fqn, err +// RETURNING +// COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, +// COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, +// COALESCE(value_id::TEXT, '')::TEXT as value_id, +// fqn +func (q *Queries) UpsertAttributeDefinitionFqn(ctx context.Context, attributeID string) ([]UpsertAttributeDefinitionFqnRow, error) { + rows, err := q.db.Query(ctx, upsertAttributeDefinitionFqn, attributeID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []UpsertAttributeDefinitionFqnRow + for rows.Next() { + var i UpsertAttributeDefinitionFqnRow + if err := rows.Scan( + &i.NamespaceID, + &i.AttributeID, + &i.ValueID, + &i.Fqn, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil } -const upsertAttributeNamespaceFqn = `-- name: UpsertAttributeNamespaceFqn :one +const upsertAttributeNamespaceFqn = `-- name: UpsertAttributeNamespaceFqn :many +WITH new_fqns_cte AS ( + -- get namespace fqns + SELECT + ns.id as namespace_id, + NULL::UUID as attribute_id, + NULL::UUID as value_id, + CONCAT('https://', ns.name) AS fqn + FROM attribute_namespaces ns + WHERE ns.id = $1 + UNION + -- get attribute definition fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + NULL::UUID as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name) AS fqn + FROM attribute_definitions ad + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ns.id = $1 + UNION + -- get attribute value fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + av.id as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn + FROM attribute_values av + JOIN attribute_definitions ad on av.attribute_definition_id = ad.id + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE ns.id = $1 +) INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) -SELECT - n.id, - NULL, - NULL, - CONCAT('https://', n.name) AS fqn -FROM attribute_namespaces n -WHERE n.id = $1 +SELECT + namespace_id, + attribute_id, + value_id, + fqn +FROM new_fqns_cte ON CONFLICT (namespace_id, attribute_id, value_id) DO UPDATE SET fqn = EXCLUDED.fqn -RETURNING fqn +RETURNING + COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, + COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, + COALESCE(value_id::TEXT, '')::TEXT as value_id, + fqn ` +type UpsertAttributeNamespaceFqnRow struct { + NamespaceID string `json:"namespace_id"` + AttributeID string `json:"attribute_id"` + ValueID string `json:"value_id"` + Fqn string `json:"fqn"` +} + // UpsertAttributeNamespaceFqn // +// WITH new_fqns_cte AS ( +// -- get namespace fqns +// SELECT +// ns.id as namespace_id, +// NULL::UUID as attribute_id, +// NULL::UUID as value_id, +// CONCAT('https://', ns.name) AS fqn +// FROM attribute_namespaces ns +// WHERE ns.id = $1 +// UNION +// -- get attribute definition fqns +// SELECT +// ns.id as namespace_id, +// ad.id as attribute_id, +// NULL::UUID as value_id, +// CONCAT('https://', ns.name, '/attr/', ad.name) AS fqn +// FROM attribute_definitions ad +// JOIN attribute_namespaces ns on ad.namespace_id = ns.id +// WHERE ns.id = $1 +// UNION +// -- get attribute value fqns +// SELECT +// ns.id as namespace_id, +// ad.id as attribute_id, +// av.id as value_id, +// CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn +// FROM attribute_values av +// JOIN attribute_definitions ad on av.attribute_definition_id = ad.id +// JOIN attribute_namespaces ns on ad.namespace_id = ns.id +// WHERE ns.id = $1 +// ) // INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) // SELECT -// n.id, -// NULL, -// NULL, -// CONCAT('https://', n.name) AS fqn -// FROM attribute_namespaces n -// WHERE n.id = $1 +// namespace_id, +// attribute_id, +// value_id, +// fqn +// FROM new_fqns_cte // ON CONFLICT (namespace_id, attribute_id, value_id) // DO UPDATE // SET fqn = EXCLUDED.fqn -// RETURNING fqn -func (q *Queries) UpsertAttributeNamespaceFqn(ctx context.Context, id string) (string, error) { - row := q.db.QueryRow(ctx, upsertAttributeNamespaceFqn, id) - var fqn string - err := row.Scan(&fqn) - return fqn, err +// RETURNING +// COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, +// COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, +// COALESCE(value_id::TEXT, '')::TEXT as value_id, +// fqn +func (q *Queries) UpsertAttributeNamespaceFqn(ctx context.Context, namespaceID string) ([]UpsertAttributeNamespaceFqnRow, error) { + rows, err := q.db.Query(ctx, upsertAttributeNamespaceFqn, namespaceID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []UpsertAttributeNamespaceFqnRow + for rows.Next() { + var i UpsertAttributeNamespaceFqnRow + if err := rows.Scan( + &i.NamespaceID, + &i.AttributeID, + &i.ValueID, + &i.Fqn, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil } -const upsertAttributeValueFqn = `-- name: UpsertAttributeValueFqn :one +const upsertAttributeValueFqn = `-- name: UpsertAttributeValueFqn :many +WITH new_fqns_cte AS ( + -- get attribute value fqns + SELECT + ns.id as namespace_id, + ad.id as attribute_id, + av.id as value_id, + CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn + FROM attribute_values av + JOIN attribute_definitions ad on av.attribute_definition_id = ad.id + JOIN attribute_namespaces ns on ad.namespace_id = ns.id + WHERE av.id = $1 +) INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) -SELECT - n.id, - ad.id, - av.id, - CONCAT('https://', n.name, '/attr/', ad.name, '/value/', av.value) AS fqn -FROM attribute_namespaces n -JOIN attribute_definitions ad ON n.id = ad.namespace_id -JOIN attribute_values av ON ad.id = av.attribute_definition_id -WHERE av.id = $1 +SELECT + namespace_id, + attribute_id, + value_id, + fqn +FROM new_fqns_cte ON CONFLICT (namespace_id, attribute_id, value_id) DO UPDATE SET fqn = EXCLUDED.fqn -RETURNING fqn +RETURNING + COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, + COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, + COALESCE(value_id::TEXT, '')::TEXT as value_id, + fqn ` +type UpsertAttributeValueFqnRow struct { + NamespaceID string `json:"namespace_id"` + AttributeID string `json:"attribute_id"` + ValueID string `json:"value_id"` + Fqn string `json:"fqn"` +} + // -------------------------------------------------------------- // ATTRIBUTE FQN // -------------------------------------------------------------- // +// WITH new_fqns_cte AS ( +// -- get attribute value fqns +// SELECT +// ns.id as namespace_id, +// ad.id as attribute_id, +// av.id as value_id, +// CONCAT('https://', ns.name, '/attr/', ad.name, '/value/', av.value) AS fqn +// FROM attribute_values av +// JOIN attribute_definitions ad on av.attribute_definition_id = ad.id +// JOIN attribute_namespaces ns on ad.namespace_id = ns.id +// WHERE av.id = $1 +// ) // INSERT INTO attribute_fqns (namespace_id, attribute_id, value_id, fqn) // SELECT -// n.id, -// ad.id, -// av.id, -// CONCAT('https://', n.name, '/attr/', ad.name, '/value/', av.value) AS fqn -// FROM attribute_namespaces n -// JOIN attribute_definitions ad ON n.id = ad.namespace_id -// JOIN attribute_values av ON ad.id = av.attribute_definition_id -// WHERE av.id = $1 +// namespace_id, +// attribute_id, +// value_id, +// fqn +// FROM new_fqns_cte // ON CONFLICT (namespace_id, attribute_id, value_id) // DO UPDATE // SET fqn = EXCLUDED.fqn -// RETURNING fqn -func (q *Queries) UpsertAttributeValueFqn(ctx context.Context, id string) (string, error) { - row := q.db.QueryRow(ctx, upsertAttributeValueFqn, id) - var fqn string - err := row.Scan(&fqn) - return fqn, err +// RETURNING +// COALESCE(namespace_id::TEXT, '')::TEXT as namespace_id, +// COALESCE(attribute_id::TEXT, '')::TEXT as attribute_id, +// COALESCE(value_id::TEXT, '')::TEXT as value_id, +// fqn +func (q *Queries) UpsertAttributeValueFqn(ctx context.Context, valueID string) ([]UpsertAttributeValueFqnRow, error) { + rows, err := q.db.Query(ctx, upsertAttributeValueFqn, valueID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []UpsertAttributeValueFqnRow + for rows.Next() { + var i UpsertAttributeValueFqnRow + if err := rows.Scan( + &i.NamespaceID, + &i.AttributeID, + &i.ValueID, + &i.Fqn, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil } diff --git a/service/policy/db/schema_erd.md b/service/policy/db/schema_erd.md index dbd11b2cf..ecb00d170 100644 --- a/service/policy/db/schema_erd.md +++ b/service/policy/db/schema_erd.md @@ -65,6 +65,7 @@ erDiagram timestamp_with_time_zone created_at uuid id PK "Primary key for the table" jsonb metadata "Metadata for the KAS (see protos for structure)" + character_varying name UK jsonb public_key "Public key of the KAS (see protos for structure/options)" timestamp_with_time_zone updated_at character_varying uri UK "URI of the KAS" @@ -73,6 +74,7 @@ erDiagram resource_mapping_groups { timestamp_with_time_zone created_at uuid id PK "Primary key for the table" + jsonb metadata character_varying name UK "Name for the group of resource mappings" uuid namespace_id FK,UK "Foreign key to the namespace of the attribute" timestamp_with_time_zone updated_at diff --git a/service/policy/db/subject_mappings.go b/service/policy/db/subject_mappings.go index 558ca7f22..7a552462a 100644 --- a/service/policy/db/subject_mappings.go +++ b/service/policy/db/subject_mappings.go @@ -5,14 +5,10 @@ import ( "encoding/json" "errors" "fmt" - "log/slog" - sq "github.com/Masterminds/squirrel" - "github.com/jackc/pgx/v5" "github.com/opentdf/platform/protocol/go/common" "github.com/opentdf/platform/protocol/go/policy" "github.com/opentdf/platform/protocol/go/policy/subjectmapping" - "github.com/opentdf/platform/service/logger" "github.com/opentdf/platform/service/pkg/db" "google.golang.org/protobuf/encoding/protojson" ) @@ -66,9 +62,7 @@ func marshalActionsProto(actions []*policy.Action) ([]byte, error) { } func unmarshalActionsProto(actionsJSON []byte, actions *[]*policy.Action) error { - var ( - raw []json.RawMessage - ) + var raw []json.RawMessage if actionsJSON != nil { if err := json.Unmarshal(actionsJSON, &raw); err != nil { @@ -87,97 +81,6 @@ func unmarshalActionsProto(actionsJSON []byte, actions *[]*policy.Action) error return nil } -func subjectMappingSelect() sq.SelectBuilder { - t := Tables.SubjectMappings - avT := Tables.AttributeValues - scsT := Tables.SubjectConditionSet - adT := Tables.Attributes - nsT := Tables.Namespaces - return db.NewStatementBuilder().Select( - t.Field("id"), - t.Field("actions"), - constructMetadata(t.Name(), false), - "JSON_BUILD_OBJECT("+ - "'id', "+scsT.Field("id")+", "+ - constructMetadata(scsT.Name(), true)+ - "'subject_sets', "+scsT.Field("condition")+ - ") AS subject_condition_set", - "JSON_BUILD_OBJECT("+ - "'id', av.id,"+ - "'value', av.value,"+ - "'active', av.active"+ - ") AS attribute_value", - ). - LeftJoin(avT.Name() + " av ON " + t.Field("attribute_value_id") + " = " + "av.id"). - LeftJoin(adT.Name() + " ad ON av.attribute_definition_id = ad.id"). - LeftJoin(nsT.Name() + " ns ON ad.namespace_id = ns.id"). - GroupBy("av.id"). - GroupBy(t.Field("id")). - LeftJoin(scsT.Name() + " ON " + scsT.Field("id") + " = " + t.Field("subject_condition_set_id")). - GroupBy(scsT.Field("id")) -} - -func subjectMappingHydrateItem(row pgx.Row) (*policy.SubjectMapping, error) { - var ( - id string - actionsJSON []byte - metadataJSON []byte - scsJSON []byte - attributeValueJSON []byte - ) - - err := row.Scan( - &id, - &actionsJSON, - &metadataJSON, - &scsJSON, - &attributeValueJSON, - ) - if err != nil { - return nil, db.WrapIfKnownInvalidQueryErr(err) - } - - m := &common.Metadata{} - if err = unmarshalMetadata(metadataJSON, m); err != nil { - return nil, err - } - - av := &policy.Value{} - if err = unmarshalAttributeValue(attributeValueJSON, av); err != nil { - return nil, err - } - - a := []*policy.Action{} - if err = unmarshalActionsProto(actionsJSON, &a); err != nil { - return nil, err - } - - scs := policy.SubjectConditionSet{} - if err = unmarshalSubjectConditionSet(scsJSON, &scs); err != nil { - return nil, err - } - - return &policy.SubjectMapping{ - Id: id, - Metadata: m, - AttributeValue: av, - SubjectConditionSet: &scs, - Actions: a, - }, nil -} - -func subjectMappingHydrateList(rows pgx.Rows) ([]*policy.SubjectMapping, error) { - list := make([]*policy.SubjectMapping, 0) - for rows.Next() { - s, err := subjectMappingHydrateItem(rows) - if err != nil { - return nil, err - } - list = append(list, s) - } - return list, nil -} - /* Subject Condition Sets */ @@ -520,100 +423,45 @@ func (c PolicyDBClient) DeleteSubjectMapping(ctx context.Context, id string) (*p }, nil } -// This function generates a SQL select statement for SubjectMappings that based on external Subject property fields & values. This relationship -// is sometimes called Entitlements or Subject Entitlements. -// -// There is complexity in the SQL generation due to the external fields/values being stored in a JSONB column on the subject_condition_set table -// and the JSON structure being SubjectSets -> ConditionGroups -> Conditions. -// -// Unfortunately we must do some slight filtering at the SQL level to avoid extreme and potentially non-rare edge cases. Subject Mappings will -// be returned if there is any condition found among the structures that matches: -// 1. The external field, external value, and an IN operator -// 2. The external field, _no_ external value, and a NOT_IN operator +// GetMatchedSubjectMappings liberally returns a list of SubjectMappings based on the provided SubjectProperties. +// The SubjectMappings are returned if an external selector field matches. // -// Without this filtering, if a selector value was something like '.emailAddress' or '.username', every Subject is probably going to relate to that mapping -// in some way or another. This could theoretically be every attribute in the DB if a policy admin has relied heavily on that field. -// -// NOTE: if you have any issues, set the log level to 'debug' for more comprehensive context. -func selectMatchedSubjectMappingsSQL(subjectProperties []*policy.SubjectProperty, logger *logger.Logger) (string, []interface{}, error) { - var err error - if len(subjectProperties) == 0 { - err = errors.Join(db.ErrMissingValue, errors.New("one or more subject properties is required")) - logger.Error("subject property missing required value", slog.Any("properties provided", subjectProperties), slog.String("error", err.Error())) - return "", nil, err - } - where := "(" - for i, sp := range subjectProperties { - if sp.GetExternalSelectorValue() == "" || sp.GetExternalValue() == "" { - err = errors.Join(db.ErrMissingValue, errors.New("all subject properties must include defined external selector value and value")) - logger.Error("subject property missing required value", slog.Any("properties provided", subjectProperties), slog.String("error", err.Error())) - return "", nil, err - } - if i > 0 { - where += " OR " - } - - hasField := "each_condition->>'subject_external_selector_value' = '" + sp.GetExternalSelectorValue() + "'" - hasValue := "(each_condition->>'subject_external_values')::jsonb @> '[\"" + sp.GetExternalValue() + "\"]'::jsonb" - hasInOperator := "each_condition->>'operator' = 'SUBJECT_MAPPING_OPERATOR_ENUM_IN'" - hasNotInOperator := "each_condition->>'operator' = 'SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN'" - // Parses the json and matches the row if either of the following conditions are met: - where += "((" + hasField + " AND " + hasValue + " AND " + hasInOperator + ")" + - " OR " + - "(" + hasField + " AND NOT " + hasValue + " AND " + hasNotInOperator + "))" - logger.Debug("current condition filter WHERE clause", slog.String("subject_external_selector_value", sp.GetExternalSelectorValue()), slog.String("subject_external_value", sp.GetExternalValue()), slog.String("where", where)) - } - where += ")" - - t := Tables.SubjectConditionSet - smT := Tables.SubjectMappings - - whereSubQ, _, err := db.NewStatementBuilder(). - // SELECT 1 is consumed by EXISTS clause, not true selection of data - Select("1"). - From("jsonb_array_elements(" + t.Field("condition") + ") AS ss" + - ", jsonb_array_elements(ss->'condition_groups') AS cg" + - ", jsonb_array_elements(cg->'conditions') AS each_condition"). - Where(where). - ToSql() +// NOTE: Any matched SubjectMappings cannot entitle without resolution of the Condition Sets returned. Each contains +// logic that must be applied to a subject Entity Representation to assure entitlement. +func (c PolicyDBClient) GetMatchedSubjectMappings(ctx context.Context, properties []*policy.SubjectProperty) ([]*policy.SubjectMapping, error) { + selectors := []string{} + for _, sp := range properties { + selectors = append(selectors, sp.GetExternalSelectorValue()) + } + list, err := c.Queries.MatchSubjectMappings(ctx, selectors) if err != nil { - logger.Error("could not generate SQL for subject entitlements", slog.String("error", err.Error())) - return "", nil, err + return nil, db.WrapIfKnownInvalidQueryErr(err) } - logger.Debug("checking for existence of any condition in the SubjectSets > ConditionGroups > Conditions that matches the provided subject properties", slog.String("where", whereSubQ)) - return subjectMappingSelect(). - From(smT.Name()). - // ensure namespace, definition, and value of mapped attribute are all active - Where("ns.active = true AND ad.active = true AND av.active = true AND EXISTS (" + whereSubQ + ")"). - ToSql() -} + mappings := make([]*policy.SubjectMapping, len(list)) + for i, sm := range list { + av := &policy.Value{} + if err = unmarshalAttributeValue(sm.AttributeValue, av); err != nil { + return nil, err + } -// GetMatchedSubjectMappings liberally returns a list of SubjectMappings based on the provided SubjectProperties. The SubjectMappings are returned -// if there is any single condition found among the structures that matches: -// 1. The external field, external value, and an IN operator -// 2. The external field, _no_ external value, and a NOT_IN operator -// -// Without this filtering, if a field was something like '.emailAddress' or '.username', every Subject is probably going to relate to that mapping -// in some way or another, potentially matching every single attribute in the DB if a policy admin has relied heavily on that field. There is no -// logic applied beyond a single condition within the query to avoid business logic interpreting the supplied conditions beyond the bare minimum -// initial filter. -// -// NOTE: This relationship is sometimes called Entitlements or Subject Entitlements. -// NOTE: if you have any issues, set the log level to 'debug' for more comprehensive context. -func (c PolicyDBClient) GetMatchedSubjectMappings(ctx context.Context, properties []*policy.SubjectProperty) ([]*policy.SubjectMapping, error) { - sql, args, err := selectMatchedSubjectMappingsSQL(properties, c.logger) - c.logger.Debug("generated SQL for subject entitlements", slog.Any("properties", properties), slog.String("sql", sql), slog.Any("args", args)) - if err != nil { - return nil, err - } + a := []*policy.Action{} + if err = unmarshalActionsProto(sm.Actions, &a); err != nil { + return nil, err + } - rows, err := c.Query(ctx, sql, args) - c.logger.Debug("executed SQL for subject entitlements", slog.Any("properties", properties), slog.String("sql", sql), slog.Any("args", args), slog.Any("rows", rows), slog.Any("error", err)) - if err != nil { - return nil, err + scs := &policy.SubjectConditionSet{} + if err = unmarshalSubjectConditionSet(sm.SubjectConditionSet, scs); err != nil { + return nil, err + } + + mappings[i] = &policy.SubjectMapping{ + Id: sm.ID, + AttributeValue: av, + SubjectConditionSet: scs, + Actions: a, + } } - defer rows.Close() - return subjectMappingHydrateList(rows) + return mappings, nil } diff --git a/service/policy/db/utils.go b/service/policy/db/utils.go index 3a6b67d9f..30864bb90 100644 --- a/service/policy/db/utils.go +++ b/service/policy/db/utils.go @@ -10,20 +10,6 @@ import ( "google.golang.org/protobuf/encoding/protojson" ) -func constructMetadata(table string, isJSON bool) string { - if table != "" { - table += "." - } - metadata := "JSON_STRIP_NULLS(JSON_BUILD_OBJECT('labels', " + table + "metadata->'labels', 'created_at', " + table + "created_at, 'updated_at', " + table + "updated_at))" - - if isJSON { - metadata = "'metadata', " + metadata + ", " - } else { - metadata += " AS metadata" - } - return metadata -} - func unmarshalMetadata(metadataJSON []byte, m *common.Metadata) error { if metadataJSON != nil { if err := protojson.Unmarshal(metadataJSON, m); err != nil { diff --git a/service/policy/kasregistry/key_access_server_registry.proto b/service/policy/kasregistry/key_access_server_registry.proto index c62392ba9..36e96bb1c 100644 --- a/service/policy/kasregistry/key_access_server_registry.proto +++ b/service/policy/kasregistry/key_access_server_registry.proto @@ -8,7 +8,10 @@ import "google/api/annotations.proto"; import "policy/objects.proto"; message GetKeyAccessServerRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message GetKeyAccessServerResponse { KeyAccessServer key_access_server = 1; @@ -19,11 +22,29 @@ message ListKeyAccessServersResponse { repeated KeyAccessServer key_access_servers = 1; } +// TODO: optional validation below should be through a custom validator, which is too bleeding edge at present without full plugin support + message CreateKeyAccessServerRequest { // Required - string uri = 1 [(buf.validate.field).required = true]; + string uri = 1 [(buf.validate.field).cel = { + id: "uri_format", + message: "URI must be a valid URL (e.g., 'https://demo.com/') followed by additional segments. Each segment must start and end with an alphanumeric character, can contain hyphens, alphanumeric characters, and slashes.", + expression: "this.isUri()" + }]; + // Required PublicKey public_key = 2 [(buf.validate.field).required = true]; + // Optional + string name = 20 [ + (buf.validate.field).required = false, + (buf.validate.field).string.max_len = 253, + (buf.validate.field).cel = { + id: "kas_name_format", + message: "Registered KAS name must be an alphanumeric string, allowing hyphens, and underscores but not as the first or last character. The stored KAS name will be normalized to lower case.", + expression: "size(this) > 0 ? this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$') : true" + } + ]; + // Common metadata common.MetadataMutable metadata = 100; } @@ -33,10 +54,29 @@ message CreateKeyAccessServerResponse { message UpdateKeyAccessServerRequest { // Required - string id = 1 [(buf.validate.field).required = true]; - string uri = 2; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Optional + string uri = 2 [(buf.validate.field).cel = { + id: "optional_uri_format", + message: "Optional URI must be a valid URL (e.g., 'https://demo.com/') followed by additional segments. Each segment must start and end with an alphanumeric character, can contain hyphens, alphanumeric characters, and slashes.", + expression: "size(this) == 0 || this.isUri()", + }]; + // Optional PublicKey public_key = 3; + // Optional + string name = 20 [ + (buf.validate.field).required = false, + (buf.validate.field).string.max_len = 253, + (buf.validate.field).cel = { + id: "kas_name_format", + message: "Registered KAS name must be an alphanumeric string, allowing hyphens, and underscores but not as the first or last character. The stored KAS name will be normalized to lower case.", + expression: "size(this) == 0 || this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$')" + } + ]; + // Optional // Common metadata common.MetadataMutable metadata = 100; common.MetadataUpdateEnum metadata_update_behavior = 101; @@ -46,7 +86,10 @@ message UpdateKeyAccessServerResponse { } message DeleteKeyAccessServerRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message DeleteKeyAccessServerResponse { KeyAccessServer key_access_server = 1; @@ -65,18 +108,42 @@ message KeyAccessServerGrants { repeated GrantedPolicyObject value_grants = 4; } +// TODO: optional validation below should be through a custom validator, which is too bleeding edge at present without full plugin support + // LIST of KAS Grants returns flat response of grants to all policy objects. It does not // employ selectors for grants to specific policy objects or build the attribute tree relation. // If grants to a known namespace, attribute, or value are needed, use the respective // GET request to the specific policy object. message ListKeyAccessServerGrantsRequest { // Optional - // Filter LIST by either ID or URI of a registered Key Access Server. + // Filter LIST by ID of a registered Key Access Server. // If neither is provided, grants from all registered KASs to policy attribute objects are returned. - string kas_id = 1; - string kas_uri = 2; + string kas_id = 1 [(buf.validate.field).cel = { + id: "optional_uuid_format", + message: "Optional field must be a valid UUID", + expression: "size(this) == 0 || this.matches('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}')" + }]; + // Optional + // Filter LIST by URI of a registered Key Access Server. + // If none is provided, grants from all registered KASs to policy attribute objects are returned. + string kas_uri = 2 [(buf.validate.field).cel = { + id: "optional_uri_format", + message: "Optional URI must be a valid URL (e.g., 'https://demo.com/') followed by additional segments. Each segment must start and end with an alphanumeric character, can contain hyphens, alphanumeric characters, and slashes.", + expression: "size(this) == 0 || this.isUri()" + }]; + // Optional + // Filter LIST by name of a registered Key Access Server. + // If none are provided, grants from all registered KASs to policy attribute objects are returned. + string kas_name = 3 [ + (buf.validate.field).required = false, + (buf.validate.field).string.max_len = 253, + (buf.validate.field).cel = { + id: "kas_name_format", + message: "Registered KAS name must be an alphanumeric string, allowing hyphens, and underscores but not as the first or last character. The stored KAS name will be normalized to lower case.", + expression: "size(this) == 0 || this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$')" + } + ]; } - message ListKeyAccessServerGrantsResponse { repeated KeyAccessServerGrants grants = 1; } diff --git a/service/policy/kasregistry/key_access_server_registry_test.go b/service/policy/kasregistry/key_access_server_registry_test.go new file mode 100644 index 000000000..43c5d3276 --- /dev/null +++ b/service/policy/kasregistry/key_access_server_registry_test.go @@ -0,0 +1,453 @@ +package kasregistry + +import ( + "strings" + "testing" + + "github.com/bufbuild/protovalidate-go" + "github.com/opentdf/platform/protocol/go/policy" + "github.com/opentdf/platform/protocol/go/policy/kasregistry" + "github.com/stretchr/testify/require" +) + +func getValidator() *protovalidate.Validator { + v, err := protovalidate.New() + if err != nil { + panic(err) + } + return v +} + +const ( + validSecureURI = "https://example.net" + validInsecureURI = "http://local.something.com" + validUUID = "00000000-0000-0000-0000-000000000000" + errMessageUUID = "string.uuid" +) + +var ( + remotePubKey = &policy.PublicKey{ + PublicKey: &policy.PublicKey_Remote{ + Remote: validSecureURI + "/public_key", + }, + } + + fakeCachedKey = &policy.PublicKey{ + PublicKey: &policy.PublicKey_Cached{ + Cached: &policy.KasPublicKeySet{ + Keys: []*policy.KasPublicKey{ + { + Pem: "fake PEM", + }, + }, + }, + }, + } + fakeURI = "https://someuri.com" + fakeID = "6321ea85-ca04-466f-aefb-174bcdbc0612" +) + +func Test_GetKeyAccessServerRequest_Succeeds(t *testing.T) { + req := &kasregistry.GetKeyAccessServerRequest{} + v := getValidator() + + err := v.Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req.Id = validUUID + err = v.Validate(req) + require.NoError(t, err) +} + +func Test_DeleteKeyAccessServerRequest_Succeeds(t *testing.T) { + req := &kasregistry.DeleteKeyAccessServerRequest{} + v := getValidator() + + err := v.Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req.Id = validUUID + err = v.Validate(req) + require.NoError(t, err) +} + +func Test_ListKeyAccessServerGrantsRequest_Fails(t *testing.T) { + v := getValidator() + bad := []struct { + id string + uri string + scenario string + }{ + { + "", + "missing.scheme", + "bad URI format", + }, + { + "bad-id-format", + validSecureURI, + "invalid UUID", + }, + } + + for _, test := range bad { + req := &kasregistry.ListKeyAccessServerGrantsRequest{ + KasId: test.id, + KasUri: test.uri, + } + err := v.Validate(req) + require.Error(t, err, test.scenario) + } +} + +func Test_ListKeyAccessServerGrantsRequest_Succeeds(t *testing.T) { + v := getValidator() + + good := []struct { + id string + uri string + scenario string + }{ + { + validUUID, + validSecureURI, + "both https URI and ID", + }, + { + validUUID, + validInsecureURI, + "both http URI and ID", + }, + { + validUUID, + "", + "no optional URI", + }, + { + "", + validSecureURI, + "no optional KAS ID", + }, + { + "", + "", + "neither optional ID nor URI", + }, + } + + for _, test := range good { + req := &kasregistry.ListKeyAccessServerGrantsRequest{ + KasId: test.id, + KasUri: test.uri, + } + err := v.Validate(req) + require.NoError(t, err, test.scenario) + } +} + +func Test_CreateKeyAccessServer_Succeeds(t *testing.T) { + good := []struct { + uri string + key *policy.PublicKey + name string + scenario string + }{ + { + fakeURI, + fakeCachedKey, + "", + "no optional KAS name & cached key", + }, + { + fakeURI, + fakeCachedKey, + "kas_name", + "included KAS name & cached key", + }, + { + fakeURI, + fakeCachedKey, + "kas-name", + "hyphenated KAS name", + }, + { + fakeURI, + fakeCachedKey, + "kas-name123", + "numeric KAS name", + }, + { + fakeURI, + fakeCachedKey, + "KASnameIsMiXeDCaSe", + "mixed case KAS name", + }, + { + fakeURI, + remotePubKey, + "", + "no optional KAS name & remote key", + }, + } + + for _, test := range good { + createReq := &kasregistry.CreateKeyAccessServerRequest{ + Uri: test.uri, + PublicKey: test.key, + Name: test.name, + } + + err := getValidator().Validate(createReq) + require.NoError(t, err, test.scenario+" should be valid") + } +} + +func Test_CreateKeyAccessServer_Fails(t *testing.T) { + bad := []struct { + uri string + key *policy.PublicKey + name string + scenario string + }{ + { + "", + fakeCachedKey, + "", + "no uri", + }, + { + fakeURI, + fakeCachedKey, + "kas name", + "kas name has spaces", + }, + { + fakeURI, + fakeCachedKey, + "kas_name_", + "kas name ends in underscore", + }, + { + fakeURI, + fakeCachedKey, + "_kas_name", + "kas name starts with underscore", + }, + { + fakeURI, + fakeCachedKey, + "kas-name-", + "kas name ends in hyphen", + }, + { + fakeURI, + fakeCachedKey, + "-kas-name", + "kas name starts with hyphen", + }, + { + fakeURI, + fakeCachedKey, + strings.Repeat("a", 254), + "name too long", + }, + { + fakeURI, + nil, + "", + "no public key", + }, + { + fakeURI, + &policy.PublicKey{ + PublicKey: &policy.PublicKey_Remote{ + Remote: "bad format", + }, + }, + "", + "remote public key bad format", + }, + } + + for _, test := range bad { + createReq := &kasregistry.CreateKeyAccessServerRequest{ + Uri: test.uri, + PublicKey: test.key, + Name: test.name, + } + + err := getValidator().Validate(createReq) + require.Error(t, err, test.scenario+" should be invalid") + } +} + +func Test_UpdateKeyAccessServer_Succeeds(t *testing.T) { + good := []struct { + uri string + key *policy.PublicKey + name string + scenario string + }{ + { + fakeURI, + fakeCachedKey, + "", + "no optional KAS name", + }, + { + fakeURI + "/somewhere-over-the-rainbow", + nil, + "", + "only URI", + }, + { + "", + fakeCachedKey, + "", + "only cached key", + }, + { + "", + remotePubKey, + "", + "only remote key", + }, + { + "", + nil, + "KASnameIsMiXeDCaSe", + "mixed case KAS name", + }, + { + fakeURI, + remotePubKey, + "new-name1", + "everything included", + }, + { + fakeURI, + fakeCachedKey, + "kas-name", + "hyphenated KAS name", + }, + { + fakeURI, + fakeCachedKey, + "kas-name123", + "numeric KAS name", + }, + } + + for _, test := range good { + updateReq := &kasregistry.UpdateKeyAccessServerRequest{ + Id: fakeID, + Uri: test.uri, + PublicKey: test.key, + Name: test.name, + } + + err := getValidator().Validate(updateReq) + require.NoError(t, err, test.scenario+" should be valid") + } +} + +func Test_UpdateKeyAccessServer_Fails(t *testing.T) { + bad := []struct { + id string + uri string + key *policy.PublicKey + name string + scenario string + }{ + { + validUUID, + fakeURI, + fakeCachedKey, + "kas name", + "kas name has spaces", + }, + { + validUUID, + fakeURI, + fakeCachedKey, + "kas_name_", + "kas name ends in underscore", + }, + { + validUUID, + fakeURI, + fakeCachedKey, + "_kas_name", + "kas name starts with underscore", + }, + { + validUUID, + fakeURI, + fakeCachedKey, + "kas-name-", + "kas name ends in hyphen", + }, + { + validUUID, + fakeURI, + fakeCachedKey, + "-kas-name", + "kas name starts with hyphen", + }, + { + validUUID, + fakeURI, + fakeCachedKey, + strings.Repeat("a", 254), + "name too long", + }, + { + validUUID, + fakeURI, + &policy.PublicKey{ + PublicKey: &policy.PublicKey_Remote{ + Remote: "bad URL", + }, + }, + "", + "remote public key bad format", + }, + { + "bad-id", + fakeURI, + fakeCachedKey, + "", + "invalid id", + }, + { + "", + fakeURI, + fakeCachedKey, + "", + "no id", + }, + } + + for _, test := range bad { + updateReq := &kasregistry.UpdateKeyAccessServerRequest{ + Id: test.id, + Uri: test.uri, + PublicKey: test.key, + Name: test.name, + } + + err := getValidator().Validate(updateReq) + require.Error(t, err, "scenario should be invalid: "+test.scenario) + } +} + +func Test_UpdateKeyAccessServer_ShouldRequireID(t *testing.T) { + updateReq := &kasregistry.UpdateKeyAccessServerRequest{ + Uri: fakeURI, + } + + err := getValidator().Validate(updateReq) + require.Error(t, err, "ID should be required") +} diff --git a/service/policy/namespaces/namespaces.proto b/service/policy/namespaces/namespaces.proto index 2189c1e13..6b66701be 100644 --- a/service/policy/namespaces/namespaces.proto +++ b/service/policy/namespaces/namespaces.proto @@ -13,8 +13,14 @@ import "policy/objects.proto"; */ message NamespaceKeyAccessServer { - string namespace_id = 1; - string key_access_server_id = 2; + // Required + string namespace_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required + string key_access_server_id = 2 [ + (buf.validate.field).string.uuid = true + ]; } /* @@ -24,13 +30,17 @@ message NamespaceKeyAccessServer { */ message GetNamespaceRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message GetNamespaceResponse { policy.Namespace namespace = 1; } message ListNamespacesRequest { + // Optional // ACTIVE by default when not specified common.ActiveStateEnum state = 1; } @@ -59,7 +69,9 @@ message CreateNamespaceResponse { message UpdateNamespaceRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; // Optional common.MetadataMutable metadata = 100; @@ -70,7 +82,10 @@ message UpdateNamespaceResponse { } message DeactivateNamespaceRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message DeactivateNamespaceResponse {} diff --git a/service/policy/namespaces/namespaces_test.go b/service/policy/namespaces/namespaces_test.go index 14e288365..58c73c40e 100644 --- a/service/policy/namespaces/namespaces_test.go +++ b/service/policy/namespaces/namespaces_test.go @@ -9,7 +9,11 @@ import ( "github.com/stretchr/testify/require" ) -var validName = "namespace.org" +const ( + validName = "namespace.org" + validUUID = "390e0058-7ae8-48f6-821c-9db07c831276" + errMessageUUID = "string.uuid" +) func getValidator() *protovalidate.Validator { v, err := protovalidate.New() @@ -109,3 +113,83 @@ func TestCreateNamespace_NameMissing_Fails(t *testing.T) { require.Contains(t, err.Error(), "name") require.Contains(t, err.Error(), "[required]") } + +func Test_GetNamespaceRequest_Succeeds(t *testing.T) { + req := &namespaces.GetNamespaceRequest{} + v := getValidator() + + err := v.Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req.Id = validUUID + err = v.Validate(req) + require.NoError(t, err) +} + +func Test_UpdateNamespaceRequest_Succeeds(t *testing.T) { + req := &namespaces.UpdateNamespaceRequest{} + v := getValidator() + + err := v.Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req.Id = validUUID + err = v.Validate(req) + require.NoError(t, err) +} + +func Test_DeactivateNamespaceRequest_Succeeds(t *testing.T) { + req := &namespaces.DeactivateNamespaceRequest{} + v := getValidator() + + err := v.Validate(req) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + + req.Id = validUUID + err = v.Validate(req) + require.NoError(t, err) +} + +func Test_NamespaceKeyAccessServer_Succeeds(t *testing.T) { + validNamespaceKas := &namespaces.NamespaceKeyAccessServer{ + NamespaceId: validUUID, + KeyAccessServerId: validUUID, + } + + err := getValidator().Validate(validNamespaceKas) + require.NoError(t, err) +} + +func Test_NamespaceKeyAccessServer_Fails(t *testing.T) { + bad := []struct { + nsID string + kasID string + }{ + { + "", + validUUID, + }, + { + validUUID, + "", + }, + { + "", + "", + }, + {}, + } + + for _, test := range bad { + invalidNamespaceKAS := &namespaces.NamespaceKeyAccessServer{ + NamespaceId: test.nsID, + KeyAccessServerId: test.kasID, + } + err := getValidator().Validate(invalidNamespaceKAS) + require.Error(t, err) + require.Contains(t, err.Error(), errMessageUUID) + } +} diff --git a/service/policy/objects.proto b/service/policy/objects.proto index 22df2e7b2..110610a65 100644 --- a/service/policy/objects.proto +++ b/service/policy/objects.proto @@ -151,20 +151,6 @@ message SubjectMapping { /** A Condition defines a rule of - - Example: Subjects with a field selected by the flattened selector "'.division'" and a value of "Accounting" or "Marketing": - { - "subject_external_selector_value": "'.division'", - "operator": "SUBJECT_MAPPING_OPERATOR_ENUM_IN", - "subject_external_values" : ["Accounting", "Marketing"] - } - - Example: Subjects that are not part of the Fantastic Four according to their alias field: - { - "subject_external_selector_value": "'.data[0].alias'", - "operator": "SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN", - "subject_external_values" : ["mister_fantastic", "the_thing", "human_torch", "invisible_woman"] - } */ message Condition { // a selector for a field value on a flattened Entity Representation (such as from idP/LDAP) @@ -220,8 +206,8 @@ message SubjectConditionSet { and the external_value is the value selected by the external_selector_value on that Entity Representation (Subject Context). These mirror the Condition. */ message SubjectProperty { - string external_selector_value = 1 [(buf.validate.field).required = true]; - string external_value = 2 [(buf.validate.field).required = true]; + string external_selector_value = 1 [(buf.validate.field).required = true, (buf.validate.field).string = {min_len: 1}]; + string external_value = 2; } /* @@ -264,10 +250,14 @@ message KeyAccessServer { string uri = 2 [(buf.validate.field).cel = { id: "uri_format", message: "URI must be a valid URL (e.g., 'https://demo.com/') followed by additional segments. Each segment must start and end with an alphanumeric character, can contain hyphens, alphanumeric characters, and slashes.", - expression: "this.matches('^https://[a-zA-Z0-9]([a-zA-Z0-9\\\\-]{0,61}[a-zA-Z0-9])?(\\\\.[a-zA-Z0-9]([a-zA-Z0-9\\\\-]{0,61}[a-zA-Z0-9])?)*(:[0-9]+)?(/.*)?$')" + expression: "this.matches('^https?://[a-zA-Z0-9]([a-zA-Z0-9\\\\-]{0,61}[a-zA-Z0-9])?(\\\\.[a-zA-Z0-9]([a-zA-Z0-9\\\\-]{0,61}[a-zA-Z0-9])?)*(:[0-9]+)?(/.*)?$')" }]; PublicKey public_key = 3; + // Optional + // Unique name of the KAS instance + string name = 20; + // Common metadata common.Metadata metadata = 100; } diff --git a/service/policy/resourcemapping/resource_mapping.proto b/service/policy/resourcemapping/resource_mapping.proto index 80fbc5540..1bbe86429 100644 --- a/service/policy/resourcemapping/resource_mapping.proto +++ b/service/policy/resourcemapping/resource_mapping.proto @@ -12,9 +12,15 @@ import "policy/objects.proto"; Resource Mapping Groups */ +// TODO: optional validation below should be through a custom validator, which is too bleeding edge at present without full plugin support + message ListResourceMappingGroupsRequest { // Optional - string namespace_id = 1; + string namespace_id = 1 [(buf.validate.field).cel = { + id: "optional_uuid_format", + message: "Optional field must be a valid UUID", + expression: "size(this) == 0 || this.matches('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}')" + }]; } message ListResourceMappingGroupsResponse { @@ -23,7 +29,9 @@ message ListResourceMappingGroupsResponse { message GetResourceMappingGroupRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message GetResourceMappingGroupResponse { @@ -32,8 +40,11 @@ message GetResourceMappingGroupResponse { message CreateResourceMappingGroupRequest { // Required - string namespace_id = 1 [(buf.validate.field).required = true]; + string namespace_id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required string name = 2 [(buf.validate.field).required = true]; // Common metadata @@ -46,12 +57,26 @@ message CreateResourceMappingGroupResponse { message UpdateResourceMappingGroupRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; // Optional - string namespace_id = 2; + string namespace_id = 2 [(buf.validate.field).cel = { + id: "optional_uuid_format", + message: "Optional field must be a valid UUID", + expression: "size(this) == 0 || this.matches('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}')" + }]; - string name = 3; + // Optional + string name = 3 [ + (buf.validate.field).string.max_len = 253, + (buf.validate.field).cel = { + id: "optional_name_format", + message: "Optional field must be an alphanumeric string, allowing hyphens and underscores but not as the first or last character. The stored group name will be normalized to lower case.", + expression: "size(this) == 0 || this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$')" + } + ]; // Common metadata common.MetadataMutable metadata = 100; @@ -64,7 +89,9 @@ message UpdateResourceMappingGroupResponse { message DeleteResourceMappingGroupRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message DeleteResourceMappingGroupResponse { @@ -77,7 +104,11 @@ message DeleteResourceMappingGroupResponse { message ListResourceMappingsRequest { // Optional - string group_id = 1; + string group_id = 1 [(buf.validate.field).cel = { + id: "optional_uuid_format", + message: "Optional field must be a valid UUID", + expression: "size(this) == 0 || this.matches('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}')" + }]; } message ListResourceMappingsResponse { @@ -112,51 +143,36 @@ message ListResourceMappingsByGroupFqnsResponse { message GetResourceMappingRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message GetResourceMappingResponse { policy.ResourceMapping resource_mapping = 1; } -/* - ### Request - - grpcurl -plaintext -d @ localhost:8080 policy.resourcemapping.ResourceMappingService/CreateResourceMapping <), normalized to lower case. string fqn = 2 [(buf.validate.field).required = true]; } @@ -58,7 +67,9 @@ message UnsafeDeleteNamespaceResponse { // Updating an Attribute can have dangerous consequences. Use with caution. message UnsafeUpdateAttributeRequest { // Required - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; // Optional // WARNING!! @@ -72,11 +83,13 @@ message UnsafeUpdateAttributeRequest { expression: "size(this) > 0 ? this.matches('^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$') : true" } ]; + // Optional // WARNING!! // Updating the rule of an Attribute will retroactively alter access to existing TDFs of the Attribute name. AttributeRuleTypeEnum rule = 3 [ (buf.validate.field).enum.defined_only = true ]; + // Optional // WARNING!! // Unsafe reordering requires the full list of values in the new order they should be stored. Updating the order of values in a HIERARCHY-rule Attribute Definition // will retroactively alter access to existing TDFs containing those values. Replacing values on an attribute in place is not supported; values can be unsafely deleted @@ -91,7 +104,10 @@ message UnsafeUpdateAttributeResponse { // Reactivating an Attribute can potentially open up an access path to existing TDFs containing the Attribute name. // Active state of any Values under this Attribute Definition will NOT be changed. message UnsafeReactivateAttributeRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message UnsafeReactivateAttributeResponse { policy.Attribute attribute = 1; @@ -104,7 +120,10 @@ message UnsafeReactivateAttributeResponse { message UnsafeDeleteAttributeRequest { // Required // UUID of the Attribute - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required // Fully Qualified Name (FQN) of Attribute Definition (i.e. https:///attr/), normalized to lower case. string fqn = 2 [(buf.validate.field).required = true]; } @@ -119,8 +138,12 @@ message UnsafeDeleteAttributeResponse { // WARNING!! // Updating an Attribute Value will retroactively alter access to existing TDFs containing the old and new Attribute Value. message UnsafeUpdateAttributeValueRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required string value = 2 [ (buf.validate.field).string.max_len = 253, (buf.validate.field).cel = { @@ -137,7 +160,10 @@ message UnsafeUpdateAttributeValueResponse { // WARNING!! // Reactivating an Attribute Value can potentially open up an access path to existing TDFs containing the Attribute Value. message UnsafeReactivateAttributeValueRequest { - string id = 1 [(buf.validate.field).required = true]; + // Required + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; } message UnsafeReactivateAttributeValueResponse { policy.Value value = 1; @@ -149,7 +175,10 @@ message UnsafeReactivateAttributeValueResponse { message UnsafeDeleteAttributeValueRequest { // Required // UUID of the Attribute Value - string id = 1 [(buf.validate.field).required = true]; + string id = 1 [ + (buf.validate.field).string.uuid = true + ]; + // Required // Fully Qualified Name (FQN) of Attribute Value (i.e. https:///attr//value/), normalized to lower case. string fqn = 2 [(buf.validate.field).required = true]; }