syntax = "proto3"; package envoy.config.rbac.v3; import "envoy/config/core/v3/address.proto"; import "envoy/config/core/v3/extension.proto"; import "envoy/config/route/v3/route_components.proto"; import "envoy/type/matcher/v3/filter_state.proto"; import "envoy/type/matcher/v3/metadata.proto"; import "envoy/type/matcher/v3/path.proto"; import "envoy/type/matcher/v3/string.proto"; import "envoy/type/v3/range.proto"; import "google/api/expr/v1alpha1/checked.proto"; import "google/api/expr/v1alpha1/syntax.proto"; import "envoy/annotations/deprecation.proto"; import "udpa/annotations/migrate.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.config.rbac.v3"; option java_outer_classname = "RbacProto"; option java_multiple_files = true; option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3;rbacv3"; option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#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 { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.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 [(validate.rules).enum = {defined_only: true}]; // 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 [(validate.rules).enum = {defined_only: true}]; // 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 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 { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.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 [(validate.rules).repeated = {min_items: 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 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control // :ref:`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 [(udpa.annotations.field_migrate).oneof_promotion = "expression_specifier"]; // [#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 [(udpa.annotations.field_migrate).oneof_promotion = "expression_specifier"]; } // Permission defines an action (or actions) that a principal can take. // [#next-free-field: 14] message Permission { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.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 { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Permission.Set"; repeated Permission rules = 1 [(validate.rules).repeated = {min_items: 1}]; } oneof rule { option (validate.required) = true; // 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 [(validate.rules).bool = {const: true}]; // 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 [(validate.rules).uint32 = {lte: 65535}]; // 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 ` // filter is not added, and if a ``FilterChainMatch`` is not defined for // the :ref:`server name // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // // * A :ref:`listener filter ` may // overwrite a connection's requested server name within Envoy. // // Please refer to :ref:`this FAQ entry ` 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; // URI template path matching. // [#extension-category: envoy.path.match] core.v3.TypedExtensionConfig uri_template = 13; } } // Principal defines an identity or a group of identities for a downstream // subject. // [#next-free-field: 13] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.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 { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; repeated Principal ids = 1 [(validate.rules).repeated = {min_items: 1}]; } // Authentication attributes for a downstream. message Authenticated { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.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 { option (validate.required) = true; // 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 [(validate.rules).bool = {const: true}]; // 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. // // This field is deprecated; either use :ref:`remote_ip // ` for the same // behavior, or use // :ref:`direct_remote_ip `. core.v3.CidrRange source_ip = 5 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the // :ref:`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 // `. 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; // Identifies the principal using a filter state object. type.matcher.v3.FilterStateMatcher filter_state = 12; // 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; } } // Action defines the result of allowance or denial when a request matches the matcher. message Action { // The name indicates the policy name. string name = 1 [(validate.rules).string = {min_len: 1}]; // The action to take if the matcher matches. Every action either allows or denies a request, // and can also carry out action-specific operations. // // Actions: // // * ``ALLOW``: If the request gets matched on ALLOW, it is permitted. // * ``DENY``: If the request gets matched on DENY, it is not permitted. // * ``LOG``: If the request gets matched on LOG, it is permitted. Besides, the // dynamic metadata key ``access_log_hint`` under the shared key namespace // ``envoy.common`` will be set to the value ``true``. // * If the request cannot get matched, it will fallback to ``DENY``. // // Log behavior: // // If the RBAC matcher contains at least one LOG action, the dynamic // metadata key ``access_log_hint`` will be set based on if the request // get matched on the LOG action. // RBAC.Action action = 2; }