| // |
| // Copyright 2021 gRPC authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| // Local copy of Envoy xDS proto file, used for testing only. |
| |
| syntax = "proto3"; |
| |
| package envoy.config.rbac.v3; |
| |
| import "src/proto/grpc/testing/xds/v3/address.proto"; |
| import "src/proto/grpc/testing/xds/v3/extension.proto"; |
| import "src/proto/grpc/testing/xds/v3/route.proto"; |
| import "src/proto/grpc/testing/xds/v3/metadata.proto"; |
| import "src/proto/grpc/testing/xds/v3/path.proto"; |
| import "src/proto/grpc/testing/xds/v3/string.proto"; |
| import "src/proto/grpc/testing/xds/v3/range.proto"; |
| |
| import "src/proto/grpc/testing/xds/v3/expr.proto"; |
| |
| // [#protodoc-title: Role Based Access Control (RBAC)] |
| |
| // Role Based Access Control (RBAC) provides service-level and method-level access control for a |
| // service. Requests are allowed or denied based on the `action` and whether a matching policy is |
| // found. For instance, if the action is ALLOW and a matching policy is found the request should be |
| // allowed. |
| // |
| // RBAC can also be used to make access logging decisions by communicating with access loggers |
| // through dynamic metadata. When the action is LOG and at least one policy matches, the |
| // `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating |
| // the request should be logged. |
| // |
| // Here is an example of RBAC configuration. It has two policies: |
| // |
| // * Service account "cluster.local/ns/default/sa/admin" has full access to the service, and so |
| // does "cluster.local/ns/default/sa/superuser". |
| // |
| // * Any user can read ("GET") the service at paths with prefix "/products", so long as the |
| // destination port is either 80 or 443. |
| // |
| // .. code-block:: yaml |
| // |
| // action: ALLOW |
| // policies: |
| // "service-admin": |
| // permissions: |
| // - any: true |
| // principals: |
| // - authenticated: |
| // principal_name: |
| // exact: "cluster.local/ns/default/sa/admin" |
| // - authenticated: |
| // principal_name: |
| // exact: "cluster.local/ns/default/sa/superuser" |
| // "product-viewer": |
| // permissions: |
| // - and_rules: |
| // rules: |
| // - header: |
| // name: ":method" |
| // string_match: |
| // exact: "GET" |
| // - url_path: |
| // path: { prefix: "/products" } |
| // - or_rules: |
| // rules: |
| // - destination_port: 80 |
| // - destination_port: 443 |
| // principals: |
| // - any: true |
| // |
| message RBAC { |
| // Should we do safe-list or block-list style access control? |
| enum Action { |
| // The policies grant access to principals. The rest are denied. This is safe-list style |
| // access control. This is the default type. |
| ALLOW = 0; |
| |
| // The policies deny access to principals. The rest are allowed. This is block-list style |
| // access control. |
| DENY = 1; |
| |
| // The policies set the `access_log_hint` dynamic metadata key based on if requests match. |
| // All requests are allowed. |
| LOG = 2; |
| } |
| |
| message AuditLoggingOptions { |
| // Deny and allow here refer to RBAC decisions, not actions. |
| enum AuditCondition { |
| // Never audit. |
| NONE = 0; |
| |
| // Audit when RBAC denies the request. |
| ON_DENY = 1; |
| |
| // Audit when RBAC allows the request. |
| ON_ALLOW = 2; |
| |
| // Audit whether RBAC allows or denies the request. |
| ON_DENY_AND_ALLOW = 3; |
| } |
| |
| // [#not-implemented-hide:] |
| message AuditLoggerConfig { |
| // Typed logger configuration. |
| // |
| // [#extension-category: envoy.rbac.audit_loggers] |
| core.v3.TypedExtensionConfig audit_logger = 1; |
| |
| // If true, when the logger is not supported, the data plane will not NACK but simply ignore it. |
| bool is_optional = 2; |
| } |
| |
| // Condition for the audit logging to happen. |
| // If this condition is met, all the audit loggers configured here will be invoked. |
| // |
| // [#not-implemented-hide:] |
| AuditCondition audit_condition = 1; |
| |
| // Configurations for RBAC-based authorization audit loggers. |
| // |
| // [#not-implemented-hide:] |
| repeated AuditLoggerConfig logger_configs = 2; |
| } |
| |
| // The action to take if a policy matches. Every action either allows or denies a request, |
| // and can also carry out action-specific operations. |
| // |
| // Actions: |
| // |
| // * ALLOW: Allows the request if and only if there is a policy that matches |
| // the request. |
| // * DENY: Allows the request if and only if there are no policies that |
| // match the request. |
| // * LOG: Allows all requests. If at least one policy matches, the dynamic |
| // metadata key `access_log_hint` is set to the value `true` under the shared |
| // key namespace 'envoy.common'. If no policies match, it is set to `false`. |
| // Other actions do not modify this key. |
| // |
| Action action = 1; |
| |
| // Maps from policy name to policy. A match occurs when at least one policy matches the request. |
| // The policies are evaluated in lexicographic order of the policy name. |
| map<string, Policy> policies = 2; |
| |
| // Audit logging options that include the condition for audit logging to happen |
| // and audit logger configurations. |
| // |
| // [#not-implemented-hide:] |
| AuditLoggingOptions audit_logging_options = 3; |
| } |
| |
| // Policy specifies a role and the principals that are assigned/denied the role. |
| // A policy matches if and only if at least one of its permissions match the |
| // action taking place AND at least one of its principals match the downstream |
| // AND the condition is true if specified. |
| message Policy { |
| // Required. The set of permissions that define a role. Each permission is |
| // matched with OR semantics. To match all actions for this policy, a single |
| // Permission with the `any` field set to true should be used. |
| repeated Permission permissions = 1; |
| |
| // Required. The set of principals that are assigned/denied the role based on |
| // “action”. Each principal is matched with OR semantics. To match all |
| // downstreams for this policy, a single Principal with the `any` field set to |
| // true should be used. |
| repeated Principal principals = 2; |
| |
| // An optional symbolic expression specifying an access control |
| // :ref:`condition <arch_overview_condition>`. The condition is combined |
| // with the permissions and the principals as a clause with AND semantics. |
| // Only be used when checked_condition is not used. |
| google.api.expr.v1alpha1.Expr condition = 3; |
| |
| // [#not-implemented-hide:] |
| // An optional symbolic expression that has been successfully type checked. |
| // Only be used when condition is not used. |
| google.api.expr.v1alpha1.CheckedExpr checked_condition = 4; |
| } |
| |
| // Permission defines an action (or actions) that a principal can take. |
| // [#next-free-field: 13] |
| message Permission { |
| // Used in the `and_rules` and `or_rules` fields in the `rule` oneof. Depending on the context, |
| // each are applied with the associated behavior. |
| message Set { |
| repeated Permission rules = 1; |
| } |
| |
| oneof rule { |
| // A set of rules that all must match in order to define the action. |
| Set and_rules = 1; |
| |
| // A set of rules where at least one must match in order to define the action. |
| Set or_rules = 2; |
| |
| // When any is set, it matches any action. |
| bool any = 3; |
| |
| // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only |
| // available for HTTP request. |
| // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` |
| // field if you want to match the URL path without the query and fragment string. |
| route.v3.HeaderMatcher header = 4; |
| |
| // A URL path on the incoming HTTP request. Only available for HTTP. |
| type.matcher.v3.PathMatcher url_path = 10; |
| |
| // A CIDR block that describes the destination IP. |
| core.v3.CidrRange destination_ip = 5; |
| |
| // A port number that describes the destination port connecting to. |
| uint32 destination_port = 6; |
| |
| // A port number range that describes a range of destination ports connecting to. |
| type.v3.Int32Range destination_port_range = 11; |
| |
| // Metadata that describes additional information about the action. |
| type.matcher.v3.MetadataMatcher metadata = 7; |
| |
| // Negates matching the provided permission. For instance, if the value of |
| // `not_rule` would match, this permission would not match. Conversely, if |
| // the value of `not_rule` would not match, this permission would match. |
| Permission not_rule = 8; |
| |
| // The request server from the client's connection request. This is |
| // typically TLS SNI. |
| // |
| // .. attention:: |
| // |
| // The behavior of this field may be affected by how Envoy is configured |
| // as explained below. |
| // |
| // * If the :ref:`TLS Inspector <config_listener_filters_tls_inspector>` |
| // filter is not added, and if a `FilterChainMatch` is not defined for |
| // the :ref:`server name |
| // <envoy_v3_api_field_config.listener.v3.FilterChainMatch.server_names>`, |
| // a TLS connection's requested SNI server name will be treated as if it |
| // wasn't present. |
| // |
| // * A :ref:`listener filter <arch_overview_listener_filters>` may |
| // overwrite a connection's requested server name within Envoy. |
| // |
| // Please refer to :ref:`this FAQ entry <faq_how_to_setup_sni>` to learn to |
| // setup SNI. |
| type.matcher.v3.StringMatcher requested_server_name = 9; |
| |
| // Extension for configuring custom matchers for RBAC. |
| // [#extension-category: envoy.rbac.matchers] |
| core.v3.TypedExtensionConfig matcher = 12; |
| } |
| } |
| |
| // Principal defines an identity or a group of identities for a downstream |
| // subject. |
| // [#next-free-field: 12] |
| message Principal { |
| // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. |
| // Depending on the context, each are applied with the associated behavior. |
| message Set { |
| repeated Principal ids = 1; |
| } |
| |
| // Authentication attributes for a downstream. |
| message Authenticated { |
| reserved 1; |
| |
| // The name of the principal. If set, The URI SAN or DNS SAN in that order |
| // is used from the certificate, otherwise the subject field is used. If |
| // unset, it applies to any user that is authenticated. |
| type.matcher.v3.StringMatcher principal_name = 2; |
| } |
| |
| oneof identifier { |
| // A set of identifiers that all must match in order to define the |
| // downstream. |
| Set and_ids = 1; |
| |
| // A set of identifiers at least one must match in order to define the |
| // downstream. |
| Set or_ids = 2; |
| |
| // When any is set, it matches any downstream. |
| bool any = 3; |
| |
| // Authenticated attributes that identify the downstream. |
| Authenticated authenticated = 4; |
| |
| // A CIDR block that describes the downstream IP. |
| // This address will honor proxy protocol, but will not honor XFF. |
| core.v3.CidrRange source_ip = 5; |
| |
| // A CIDR block that describes the downstream remote/origin address. |
| // Note: This is always the physical peer even if the |
| // :ref:`remote_ip <envoy_v3_api_field_config.rbac.v3.Principal.remote_ip>` is |
| // inferred from for example the x-forwarder-for header, proxy protocol, |
| // etc. |
| core.v3.CidrRange direct_remote_ip = 10; |
| |
| // A CIDR block that describes the downstream remote/origin address. |
| // Note: This may not be the physical peer and could be different from the |
| // :ref:`direct_remote_ip |
| // <envoy_v3_api_field_config.rbac.v3.Principal.direct_remote_ip>`. E.g, if the |
| // remote ip is inferred from for example the x-forwarder-for header, proxy |
| // protocol, etc. |
| core.v3.CidrRange remote_ip = 11; |
| |
| // A header (or pseudo-header such as :path or :method) on the incoming HTTP |
| // request. Only available for HTTP request. Note: the pseudo-header :path |
| // includes the query and fragment string. Use the `url_path` field if you |
| // want to match the URL path without the query and fragment string. |
| route.v3.HeaderMatcher header = 6; |
| |
| // A URL path on the incoming HTTP request. Only available for HTTP. |
| type.matcher.v3.PathMatcher url_path = 9; |
| |
| // Metadata that describes additional information about the principal. |
| type.matcher.v3.MetadataMatcher metadata = 7; |
| |
| // Negates matching the provided principal. For instance, if the value of |
| // `not_id` would match, this principal would not match. Conversely, if the |
| // value of `not_id` would not match, this principal would match. |
| Principal not_id = 8; |
| } |
| } |