From 0ceefa3442fc0a7b992e472bea046ea4e36c4e75 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Thu, 20 Sep 2018 22:42:09 +0000 Subject: [PATCH 01/16] polish jwt_authn config.proto Signed-off-by: Wayne Zhang --- api/docs/BUILD | 1 + .../http/jwt_authn/v2alpha/config.proto | 21 ++++++++++++------- docs/build.sh | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/api/docs/BUILD b/api/docs/BUILD index d26ef6d158172..da38a524aed6f 100644 --- a/api/docs/BUILD +++ b/api/docs/BUILD @@ -36,6 +36,7 @@ proto_library( "//envoy/config/filter/http/header_to_metadata/v2:header_to_metadata", "//envoy/config/filter/http/health_check/v2:health_check", "//envoy/config/filter/http/ip_tagging/v2:ip_tagging", + "//envoy/config/filter/http/jwt_authn/v2alpha:jwt_authn", "//envoy/config/filter/http/lua/v2:lua", "//envoy/config/filter/http/rate_limit/v2:rate_limit", "//envoy/config/filter/http/rbac/v2:rbac", diff --git a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto index 85e134bcc82d3..6b1de881b5ffd 100644 --- a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto +++ b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto @@ -11,10 +11,17 @@ import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; import "validate/validate.proto"; -// This message specifies how a JSON Web Token (JWT) can be verified. JWT format is defined -// `here `_. Please see `OAuth2.0 -// `_ and `OIDC1.0 `_ for -// the authentication flow. +// JWT format is defined `here `_. Please see `OAuth2.0 +// `_ and `OIDC1.0 `_ for the +// authentication flow. +// +// A JwtProvider message specifies how a JSON Web Token (JWT) can be verified. It specifies: +// +// * issuer: the principal that issues the JWT. It has to match the one from the token. +// * allowed audiences: the ones in the token have to be listed here. +// * how to fetch public key JWKS to verify the token signature. +// * how to extract JWT token in the request. +// * how to pass successfully verified token payload. // // Example: // @@ -104,17 +111,17 @@ message JwtProvider { // If no explicit location is specified, the following default locations are tried in order: // // 1. The Authorization header using the Bearer schema. See `here - // `_. Example: + // `_. Example:: // // Authorization: Bearer . // // 2. `access_token` query parameter. See `this // `_ // - + // // Multiple JWTs can be verified for a request. Each JWT has to be extracted from the locations // its issuer specified or from the default locations. - + // // Specify the HTTP headers to extract JWT token. For examples, following config: // // .. code-block:: yaml diff --git a/docs/build.sh b/docs/build.sh index ac4a5520fea08..eecdab72416ef 100755 --- a/docs/build.sh +++ b/docs/build.sh @@ -87,6 +87,7 @@ PROTO_RST=" /envoy/config/filter/http/health_check/v2/health_check/envoy/config/filter/http/health_check/v2/health_check.proto.rst /envoy/config/filter/http/header_to_metadata/v2/header_to_metadata/envoy/config/filter/http/header_to_metadata/v2/header_to_metadata.proto.rst /envoy/config/filter/http/ip_tagging/v2/ip_tagging/envoy/config/filter/http/ip_tagging/v2/ip_tagging.proto.rst + /envoy/config/filter/http/jwt_authn/v2alpha/jwt_authn/envoy/config/filter/http/jwt_authn/v2alpha/config.proto.rst /envoy/config/filter/http/lua/v2/lua/envoy/config/filter/http/lua/v2/lua.proto.rst /envoy/config/filter/http/rate_limit/v2/rate_limit/envoy/config/filter/http/rate_limit/v2/rate_limit.proto.rst /envoy/config/filter/http/rbac/v2/rbac/envoy/config/filter/http/rbac/v2/rbac.proto.rst From 47e99493b444a00c77ef18e7a3c55cd76cbc1288 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Fri, 21 Sep 2018 01:12:45 +0000 Subject: [PATCH 02/16] Fix format for jwt_authn config.proto Signed-off-by: Wayne Zhang --- .../http/jwt_authn/v2alpha/config.proto | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto index 6b1de881b5ffd..edbc4c7acfa47 100644 --- a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto +++ b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto @@ -11,9 +11,11 @@ import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; import "validate/validate.proto"; -// JWT format is defined `here `_. Please see `OAuth2.0 -// `_ and `OIDC1.0 `_ for the -// authentication flow. +// Please see following for JWT authentication flow: +// +// * `JWT format `_ +// * `OAuth2.0 `_ +// * `OIDC1.0 `_ // // A JwtProvider message specifies how a JSON Web Token (JWT) can be verified. It specifies: // @@ -39,15 +41,15 @@ import "validate/validate.proto"; // seconds: 300 // message JwtProvider { - // Identifies the principal that issued the JWT. See `here - // `_. Usually a URL or an email address. + // Specify the `principal `_ that issued + // the JWT, usually a URL or an email address. // // Example: https://securetoken.google.com // Example: 1234567-compute@developer.gserviceaccount.com // string issuer = 1 [(validate.rules).string.min_bytes = 1]; - // The list of JWT `audiences `_. that are + // The list of JWT `audiences `_ are // allowed to access. A JWT containing any of these audiences will be accepted. If not specified, // will not check audiences in the token. // @@ -61,8 +63,8 @@ message JwtProvider { // repeated string audiences = 2; - // `JSON Web Key Set `_ is needed. to validate - // signature of the JWT. This field specifies where to fetch JWKS. + // `JSON Web Key Set (JWKS) `_ is needed to + // validate signature of a JWT. This field specifies where to fetch JWKS. oneof jwks_source_specifier { option (validate.required) = true; @@ -110,17 +112,15 @@ message JwtProvider { // // If no explicit location is specified, the following default locations are tried in order: // - // 1. The Authorization header using the Bearer schema. See `here - // `_. Example:: - // - // Authorization: Bearer . + // 1. The Authorization header using the `Bearer schema + // `_. Example:: // - // 2. `access_token` query parameter. See `this - // `_ + // Authorization: Bearer . // + // 2. `access_token `_ query parameter. // // Multiple JWTs can be verified for a request. Each JWT has to be extracted from the locations - // its issuer specified or from the default locations. + // its provider specified or from the default locations. // // Specify the HTTP headers to extract JWT token. For examples, following config: // @@ -156,10 +156,6 @@ message JwtProvider { // base64_encoded(jwt_payload_in_JSON) // // If it is not specified, the payload will not be forwarded. - // Multiple JWTs in a request from different issuers will be supported. Multiple JWTs from the - // same issuer will not be supported. Each issuer can config this `forward_payload_header`. If - // multiple JWTs from different issuers want to forward their payloads, their - // `forward_payload_header` should be different. string forward_payload_header = 8; } @@ -284,7 +280,7 @@ message JwtRequirementAndList { // .. code-block:: yaml // // - match: -// prefix: "/healthz" +// prefix: "/healthz" // // In above example, "requires" field is empty for /healthz prefix match, // it means that requests matching the path prefix don't require JWT authentication. @@ -294,7 +290,7 @@ message JwtRequirementAndList { // .. code-block:: yaml // // - match: -// prefix: "/" +// prefix: "/" // requires: { provider_name: "provider-A" } // // In above example, all requests matched the path prefix require jwt authentication @@ -308,7 +304,7 @@ message RequirementRule { // .. code-block:: yaml // // match: - // prefix: "/" + // prefix: "/" // envoy.api.v2.route.RouteMatch match = 1 [(validate.rules).message.required = true]; @@ -387,17 +383,21 @@ message JwtAuthentication { // .. code-block:: yaml // // rules: - // - match: { prefix: "/healthz" } - // - match: { prefix: "/baz" } + // - match: + // prefix: "/healthz" + // - match: + // prefix: "/baz" // requires: // provider_name: "provider1" - // - match: { prefix: "/foo" } + // - match: + // prefix: "/foo" // requires: // requires_any: // requirements: // - provider_name: "provider1" // - provider_name: "provider2" - // - match: { prefix: "/bar" } + // - match: + // prefix: "/bar" // requires: // requires_all: // requirements: From e945fea37a536afdd62c048f2c5f7ef07239749d Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Fri, 21 Sep 2018 17:21:51 +0000 Subject: [PATCH 03/16] Add jwt_authn_filter.rst Signed-off-by: Wayne Zhang --- .../http_filters/http_filters.rst | 1 + .../http_filters/jwt_authn_filter.rst | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 docs/root/configuration/http_filters/jwt_authn_filter.rst diff --git a/docs/root/configuration/http_filters/http_filters.rst b/docs/root/configuration/http_filters/http_filters.rst index 91af21e0e7bf9..49900f74ac538 100644 --- a/docs/root/configuration/http_filters/http_filters.rst +++ b/docs/root/configuration/http_filters/http_filters.rst @@ -18,6 +18,7 @@ HTTP filters health_check_filter header_to_metadata_filter ip_tagging_filter + jwt_authn_filter lua_filter rate_limit_filter rbac_filter diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst new file mode 100644 index 0000000000000..a21ea56884177 --- /dev/null +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -0,0 +1,95 @@ +.. _config_http_filters_jwt_authn: + +JWT Authentication +================== + +JSON Web Token (JWT) usually is used to carry end user identity. This build-in HTTP filter can be used to authenticate JWT. + +A public key (JWKS) is needed to verify a JWT signature. It can be specified in the filter config, or can be fetched remotely from a JWKS server. If it is fetched remotely, Envoy will cache it. + +If JWT verification fails, the request will be rejected. If JWT verification success, its payload can be forwarded to the upstream if desired. + +Configuration +------------- + +Filter config uses "rules" to specify matching rules and their authentication requirements. It uses "providers" map to specify how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and how to output its payload. + +The external authorization HTTP filter calls an external gRPC or HTTP service to check if the incoming +HTTP request is authorized or not. +If the request is deemed unauthorized then the request will be denied normally with 403 (Forbidden) response. +Note that sending additional custom metadata from the authorization service to the upstream, or to the downstream is +also possible. This is explained in more details at :ref:`HTTP filter `. + +.. tip:: + It is recommended that this filter is configured first in the filter chain so that requests are + authorized prior to the rest of filters processing the request. + +The content of the requests that are passed to an authorization service is specified by +:ref:`CheckRequest `. + +.. _config_http_filters_ext_authz_http_configuration: + +The HTTP filter, using a gRPC/HTTP service, can be configured as follows. You can see all the +configuration options at +:ref:`HTTP filter `. + +Configuration Examples +----------------------------- + +A sample filter configuration for a gRPC authorization server: + +.. code-block:: yaml + + http_filters: + - name: envoy.ext_authz + config: + grpc_service: + envoy_grpc: + cluster_name: ext-authz + +.. code-block:: yaml + + clusters: + - name: ext-authz + type: static + http2_protocol_options: {} + hosts: + - socket_address: { address: 127.0.0.1, port_value: 10003 } + +A sample filter configuration for a raw HTTP authorization server: + +.. code-block:: yaml + + http_filters: + - name: envoy.ext_authz + config: + http_service: + server_uri: + uri: 127.0.0.1:10003 + cluster: ext-authz + timeout: 0.25s + failure_mode_allow: false + +.. code-block:: yaml + + clusters: + - name: ext-authz + connect_timeout: 0.25s + type: logical_dns + lb_policy: round_robin + hosts: + - socket_address: { address: 127.0.0.1, port_value: 10003 } + +Statistics +---------- +The HTTP filter outputs statistics in the *cluster..ext_authz.* namespace. + +.. csv-table:: + :header: Name, Type, Description + :widths: 1, 1, 2 + + ok, Counter, Total responses from the filter. + error, Counter, Total errors contacting the external service. + denied, Counter, Total responses from the authorizations service that were to deny the traffic. + failure_mode_allowed, Counter, "Total requests that were error(s) but were allowed through because + of failure_mode_allow set to true." From 18a967d2bf697ae27b68ae29bbbd5582bca5e42d Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Mon, 24 Sep 2018 16:19:50 +0000 Subject: [PATCH 04/16] update 2nd draft Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 87 ++++++++++++++++++- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index a21ea56884177..ebd11572a623d 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -3,17 +3,96 @@ JWT Authentication ================== -JSON Web Token (JWT) usually is used to carry end user identity. This build-in HTTP filter can be used to authenticate JWT. +This HTTP filter can be used to authenticate JSON Web Token (JWT). If JWT verification fails, the request will be rejected. If JWT verification success, its payload can be forwarded to the upstream for further authorization. A public key (JWKS) is needed to verify a JWT signature. It can be specified in the filter config, or can be fetched remotely from a JWKS server. If it is fetched remotely, Envoy will cache it. -If JWT verification fails, the request will be rejected. If JWT verification success, its payload can be forwarded to the upstream if desired. - Configuration ------------- -Filter config uses "rules" to specify matching rules and their authentication requirements. It uses "providers" map to specify how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and how to output its payload. +Filer config has two fields, "providers" and "rules". It uses "providers" to specify how JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and how to output its payload. It uses "rules" to specify request matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be verified. They will be described in details in the following sections. + +JwtProvider +~~~~~~~~~~~ + +It specifies how JWT should be verified. It has following fields: + +* issuer: the principal that issued the JWT, usually a URL or an email address +* audiences: a list of JWT audiences allowed to access. A JWT containing any of these audiences will be accepted. + If not specified, will not check audiences in the JWT +* local_jwks: fetch JWKS in local data source, either in a local file or embedded in the inline string. +* remote_jwks: fetch JWKS from a remote HTTP server, also specify cache duration. +* forward: if true, JWT will be forwarded to the upstream. +* from_headers: extract JWT from custom HTTP header. +* from_params: extract JWT from custom query parameter keys. +* forward_payload_header: forward the JWT payload in the specified HTTP header. + +Default token extract location: if "from_headers" and "from_params" is empty, the default location is from HTTP header:: + + Authorization: Bearer + +If not there, then check query parameter key "access_token" as this example:: + + /path?access_token= + +In the filer config, "providers" a map, to map provider_name to a JwtProvider message. The "provider_name" has to be unique, usually it is the same as "issuer". Multiple JwtProviders with the same issuer could be used to specify different audiences or different token extract locations. + +Config examples: + +.. code-block:: yaml + + providers: + provider_name1: + issuer: https://example.com + audiences: + - bookstore_android.apps.googleusercontent.com + - bookstore_web.apps.googleusercontent.com + remote_jwks: + http_uri: + uri: https://example.com/.well-known/jwks.json + cluster: example_jwks_cluster + cache_duration: + seconds: 300 + +Above example specifies: + +* provider_name is "provider_name1" +* issuer is https://example.com +* audiences: bookstore_android.apps.googleusercontent.com and bookstore_web.apps.googleusercontent.com +* remote_jwks: use URL "https://example.com/.well-known/jwks.json" from cluster "example_jwks_cluster", its cache duration is 300 seconds. +* token will be extracted from default locations since from_headers and from_params are empty. +* token will not be forwarded to upstream +* JWT payload will not be added to the request header. + +.. code-block:: yaml + + providers: + provider_name2: + issuer: https://example2.com + local_jwks: + inline_string: "PUBLIC-KEY" + from_headers: + - name: x-goog-iap-jwt-assertion + forward: true + forward_payload_header: x-jwt-payload + +Above example specifies: + +* provider_name is "provider_name2" +* issuer is https://example2.com +* audiences: not specified, not JWT token will not be checked. +* local_jwks: JWKS is embeded in the inline string. +* from_headers: token will be extracted from HTTP headers as:: + + x-goog-iap-jwt-assertion: . + +* forward: token will forwarded to upstream +* JWT payload will be added to the request header as:: + + x-jwt-payload: base64_encoded(jwt_payload_in_JSON) + + The external authorization HTTP filter calls an external gRPC or HTTP service to check if the incoming HTTP request is authorized or not. If the request is deemed unauthorized then the request will be denied normally with 403 (Forbidden) response. From 0e0e590ae55b42ef00ec16f8cfb907ddee43afe2 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Mon, 24 Sep 2018 22:34:59 +0000 Subject: [PATCH 05/16] update 3rd draft Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index ebd11572a623d..15b4a92a41f38 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -10,7 +10,7 @@ A public key (JWKS) is needed to verify a JWT signature. It can be specified in Configuration ------------- -Filer config has two fields, "providers" and "rules". It uses "providers" to specify how JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and how to output its payload. It uses "rules" to specify request matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be verified. They will be described in details in the following sections. +This HTTP filer config has two fields, "providers" and "rules". Field "providers" specifies how JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and how to output its payload. Field "rules" specifies matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be verified. JwtProvider ~~~~~~~~~~~ @@ -23,19 +23,19 @@ It specifies how JWT should be verified. It has following fields: * local_jwks: fetch JWKS in local data source, either in a local file or embedded in the inline string. * remote_jwks: fetch JWKS from a remote HTTP server, also specify cache duration. * forward: if true, JWT will be forwarded to the upstream. -* from_headers: extract JWT from custom HTTP header. -* from_params: extract JWT from custom query parameter keys. +* from_headers: extract JWT from custom HTTP header other than the default location. +* from_params: extract JWT from custom query parameter keys other than the default location. * forward_payload_header: forward the JWT payload in the specified HTTP header. -Default token extract location: if "from_headers" and "from_params" is empty, the default location is from HTTP header:: +The default token extract location: if "from_headers" and "from_params" is empty, the default location is from HTTP header:: Authorization: Bearer -If not there, then check query parameter key "access_token" as this example:: +If fails to extract a token from there, then check query parameter key "access_token" as this example:: /path?access_token= -In the filer config, "providers" a map, to map provider_name to a JwtProvider message. The "provider_name" has to be unique, usually it is the same as "issuer". Multiple JwtProviders with the same issuer could be used to specify different audiences or different token extract locations. +In the filter config, "providers" a map, to map provider_name to a JwtProvider message. The "provider_name" has to be unique, usually it is the same as "issuer". Multiple JwtProviders with the same issuer are allowed to specify different audiences or different token extract locations for the same issuer. Config examples: @@ -43,7 +43,7 @@ Config examples: .. code-block:: yaml providers: - provider_name1: + https://example.com: issuer: https://example.com audiences: - bookstore_android.apps.googleusercontent.com @@ -57,18 +57,18 @@ Config examples: Above example specifies: -* provider_name is "provider_name1" -* issuer is https://example.com +* provider_name is "https://example.com" +* issuer is https://example.com also. * audiences: bookstore_android.apps.googleusercontent.com and bookstore_web.apps.googleusercontent.com * remote_jwks: use URL "https://example.com/.well-known/jwks.json" from cluster "example_jwks_cluster", its cache duration is 300 seconds. -* token will be extracted from default locations since from_headers and from_params are empty. +* token will be extracted from the default extract locations since from_headers and from_params are empty. * token will not be forwarded to upstream * JWT payload will not be added to the request header. .. code-block:: yaml providers: - provider_name2: + https://example2.com: issuer: https://example2.com local_jwks: inline_string: "PUBLIC-KEY" @@ -79,22 +79,41 @@ Above example specifies: Above example specifies: -* provider_name is "provider_name2" -* issuer is https://example2.com -* audiences: not specified, not JWT token will not be checked. +* provider_name is "https://example2.com" +* issuer is https://example2.com too. +* audiences: not specified, JWT "aud" field will not be checked. * local_jwks: JWKS is embeded in the inline string. * from_headers: token will be extracted from HTTP headers as:: x-goog-iap-jwt-assertion: . * forward: token will forwarded to upstream -* JWT payload will be added to the request header as:: +* JWT payload will be added to the request header as following format:: x-jwt-payload: base64_encoded(jwt_payload_in_JSON) - -The external authorization HTTP filter calls an external gRPC or HTTP service to check if the incoming -HTTP request is authorized or not. + +RequirementRule +~~~~~~~~~~~~~~~ + +It has two fields: "match" and "requires". The field "match" to specify how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field "requires" specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such forms, such as "require_all" or "require_any". + +The field "match" uses following fields to define a match: +* one of following path_specifier: prefix, path, and regex. +* headers: specify how to match HTTP headers. +* query_parameters: specify how to match query parameters. + +The field "requires" can be specified as any one of followings: +* provider_name: specifies the provider name of required JwtProvider +* provider_and_audiences: specifies the provider with audiences. The audiences will override the one in the JwtProvider. +* requires_any: a list of requirements that if any of them success, it will be success. +* requires_all: a list of requirements that only if all of them success, it will be success. +* allow_missing_or_failed: If true, all JWT token will be verified, successfully verified JWTs will output its payload results. The request will proceeded regardless JWT is missing or any of verification failures. The typical use case is: there is another HTTP filter after this JWT filter. The JWT filter is used to do JWT verification, that filter will make decision based on the results. + + + + + HTTP request is authorized or not. If the request is deemed unauthorized then the request will be denied normally with 403 (Forbidden) response. Note that sending additional custom metadata from the authorization service to the upstream, or to the downstream is also possible. This is explained in more details at :ref:`HTTP filter `. From 59d5bfb5b4a1bbb56785b9d008df6ca835fd947d Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 25 Sep 2018 00:27:40 +0000 Subject: [PATCH 06/16] update 4th draft Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 15b4a92a41f38..4628c42353c2c 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -65,6 +65,21 @@ Above example specifies: * token will not be forwarded to upstream * JWT payload will not be added to the request header. +Important note for remote_jwks, a cluster must be created for Envoy to talk to a JWKS server. In above example, following cluster *example_jwks_cluster* is needed. + +.. code-block:: yaml + + cluster: + name: example_jwks_cluster + type: STRICT_DNS + hosts: + socket_address: + address: example.com + portValue: 80 + + +Here is another config example using inline JWKS: + .. code-block:: yaml providers: @@ -110,6 +125,31 @@ The field "requires" can be specified as any one of followings: * requires_all: a list of requirements that only if all of them success, it will be success. * allow_missing_or_failed: If true, all JWT token will be verified, successfully verified JWTs will output its payload results. The request will proceeded regardless JWT is missing or any of verification failures. The typical use case is: there is another HTTP filter after this JWT filter. The JWT filter is used to do JWT verification, that filter will make decision based on the results. +If a request matches multiple rules, the first matched rule will apply. The order of rules is important. + +If a request doesn't match any rules, or the matched rule has empty "requires" field, JWT verification is not required. + +Config samples: + +.. code-block:: yaml + + providers: + jwt_provider1: + issuer: https://example.com + remote_jwks: + http_uri: + uri: https://example.com/.well-known/jwks.json + cluster: example_jwks_cluster + cache_duration: + seconds: 300 + jwt_provider2: + issuer: https://example2.com + local_jwks: + inline_string: "PUBLIC-KEY" + from_headers: + - name: x-goog-iap-jwt-assertion + rules: + - match From dcbba99111c75d0f1d234de4c81a74b0e93f20c5 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 25 Sep 2018 17:26:27 +0000 Subject: [PATCH 07/16] 5ft draft Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 226 +++++++----------- 1 file changed, 92 insertions(+), 134 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 4628c42353c2c..b60e67433d2b2 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -3,47 +3,46 @@ JWT Authentication ================== -This HTTP filter can be used to authenticate JSON Web Token (JWT). If JWT verification fails, the request will be rejected. If JWT verification success, its payload can be forwarded to the upstream for further authorization. - -A public key (JWKS) is needed to verify a JWT signature. It can be specified in the filter config, or can be fetched remotely from a JWKS server. If it is fetched remotely, Envoy will cache it. +This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its signature, expiration time, audiences and issuer. If the JWT verification fails, its request will be rejected. If the JWT verification success, its payload could be forwarded to the upstream for further authorization if desired. JWKS needed to verify JWT signatures can be specified in the filter config or can be fetched remotely from a JWKS server. Configuration ------------- -This HTTP filer config has two fields, "providers" and "rules". Field "providers" specifies how JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and how to output its payload. Field "rules" specifies matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be verified. +This HTTP filer config has two fields, *providers* and *rules*. Field *providers* specifies how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and where to output its payload. Field *rules* specifies matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be used. JwtProvider ~~~~~~~~~~~ -It specifies how JWT should be verified. It has following fields: +It specifies how a JWT should be verified. It has following fields: -* issuer: the principal that issued the JWT, usually a URL or an email address -* audiences: a list of JWT audiences allowed to access. A JWT containing any of these audiences will be accepted. - If not specified, will not check audiences in the JWT -* local_jwks: fetch JWKS in local data source, either in a local file or embedded in the inline string. -* remote_jwks: fetch JWKS from a remote HTTP server, also specify cache duration. -* forward: if true, JWT will be forwarded to the upstream. -* from_headers: extract JWT from custom HTTP header other than the default location. -* from_params: extract JWT from custom query parameter keys other than the default location. -* forward_payload_header: forward the JWT payload in the specified HTTP header. +* *issuer*: the principal that issued the JWT, usually a URL or an email address. +* *audiences*: a list of JWT audiences allowed to access. A JWT containing any of these audiences will be accepted. + If not specified, will not check audiences in the JWT. +* *local_jwks*: fetch JWKS in local data source, either in a local file or embedded in the inline string. +* *remote_jwks*: fetch JWKS from a remote HTTP server, also specify cache duration. +* *forward*: if true, JWT will be forwarded to the upstream. +* *from_headers*: extract JWT from HTTP headers. +* *from_params*: extract JWT from query parameters. +* *forward_payload_header*: forward the JWT payload in the specified HTTP header. -The default token extract location: if "from_headers" and "from_params" is empty, the default location is from HTTP header:: +The **default extract location**. If *from_headers* and *from_params* is empty, the default location to extract JWT is from HTTP header:: Authorization: Bearer -If fails to extract a token from there, then check query parameter key "access_token" as this example:: +If fails to extract a JWT from there, then check query parameter key *access_token* as this example:: /path?access_token= -In the filter config, "providers" a map, to map provider_name to a JwtProvider message. The "provider_name" has to be unique, usually it is the same as "issuer". Multiple JwtProviders with the same issuer are allowed to specify different audiences or different token extract locations for the same issuer. +In the filter config, *providers* a map, to map *provider_name* to a *JwtProvider* message. The *provider_name* has to be unique, it is referred in the *JwtRequirement* message *provider_name* field. +Important note for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the hostname to fetch JWKS is dynamic. Config examples: .. code-block:: yaml providers: - https://example.com: + provider_name1: issuer: https://example.com audiences: - bookstore_android.apps.googleusercontent.com @@ -57,15 +56,15 @@ Config examples: Above example specifies: -* provider_name is "https://example.com" -* issuer is https://example.com also. -* audiences: bookstore_android.apps.googleusercontent.com and bookstore_web.apps.googleusercontent.com -* remote_jwks: use URL "https://example.com/.well-known/jwks.json" from cluster "example_jwks_cluster", its cache duration is 300 seconds. -* token will be extracted from the default extract locations since from_headers and from_params are empty. -* token will not be forwarded to upstream -* JWT payload will not be added to the request header. +* *provider_name* is **provider_name1** +* *issuer* is **https://example.com** +* *audiences*: **bookstore_android.apps.googleusercontent.com** and **bookstore_web.apps.googleusercontent.com** +* *remote_jwks*: use URL **https://example.com/.well-known/jwks.json** from cluster **example_jwks_cluster**, its cache duration is 300 seconds. +* token will be extracted from the default extract locations since *from_headers* and *from_params* are empty. +* token will not be forwarded to upstream since *forward* is not set, default is **false** +* JWT payload will not be added to the request header since *forward_payload_header* is not set. -Important note for remote_jwks, a cluster must be created for Envoy to talk to a JWKS server. In above example, following cluster *example_jwks_cluster* is needed. +In above example, following cluster **example_jwks_cluster** is needed. .. code-block:: yaml @@ -83,26 +82,26 @@ Here is another config example using inline JWKS: .. code-block:: yaml providers: - https://example2.com: + provider_name2: issuer: https://example2.com local_jwks: inline_string: "PUBLIC-KEY" from_headers: - - name: x-goog-iap-jwt-assertion + - name: jwt-assertion forward: true forward_payload_header: x-jwt-payload Above example specifies: -* provider_name is "https://example2.com" -* issuer is https://example2.com too. -* audiences: not specified, JWT "aud" field will not be checked. -* local_jwks: JWKS is embeded in the inline string. -* from_headers: token will be extracted from HTTP headers as:: +* *provider_name* is **provider_name2** +* *issuer* is **https://example2.com** +* *audiences*: not specified, JWT *aud* field will not be checked. +* *local_jwks*: JWKS is embeded in the inline string. +* *from_headers*: token will be extracted from HTTP headers as:: - x-goog-iap-jwt-assertion: . + jwt-assertion: . -* forward: token will forwarded to upstream +* *forward*: token will forwarded to upstream * JWT payload will be added to the request header as following format:: x-jwt-payload: base64_encoded(jwt_payload_in_JSON) @@ -111,23 +110,23 @@ Above example specifies: RequirementRule ~~~~~~~~~~~~~~~ -It has two fields: "match" and "requires". The field "match" to specify how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field "requires" specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such forms, such as "require_all" or "require_any". +It has two fields: *match* and *requires*. The field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field *requires* specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such forms, such as "require_all" or "require_any". -The field "match" uses following fields to define a match: -* one of following path_specifier: prefix, path, and regex. -* headers: specify how to match HTTP headers. -* query_parameters: specify how to match query parameters. +The field *match* uses following fields to define a match: +* one of following path_specifier: *prefix*, *path*, and *regex*. +* *headers*: specify how to match HTTP headers. +* *query_parameters*: specify how to match query parameters. -The field "requires" can be specified as any one of followings: -* provider_name: specifies the provider name of required JwtProvider -* provider_and_audiences: specifies the provider with audiences. The audiences will override the one in the JwtProvider. -* requires_any: a list of requirements that if any of them success, it will be success. -* requires_all: a list of requirements that only if all of them success, it will be success. -* allow_missing_or_failed: If true, all JWT token will be verified, successfully verified JWTs will output its payload results. The request will proceeded regardless JWT is missing or any of verification failures. The typical use case is: there is another HTTP filter after this JWT filter. The JWT filter is used to do JWT verification, that filter will make decision based on the results. +The field *requires* can be specified as any one of followings: +* *provider_name*: specifies the provider name of required JwtProvider +* *provider_and_audiences*: specifies the provider with audiences. The audiences will override the one in the JwtProvider. +* *requires_any*: a list of requirements that if any of them success, it will be success. +* *requires_all*: a list of requirements that only if all of them success, it will be success. +* *allow_missing_or_failed*: A flag for a special usage. If true, all JWTs will be verified, successfully verified JWTs will output its payload results. The request will proceeded even with some verification failures. The typical use case is: there is another HTTP filter after this filter. This JWT filter is used to do JWT verification, that filter will make decision based on the results. Istio authentication feature is implemented this way. -If a request matches multiple rules, the first matched rule will apply. The order of rules is important. +If a request matches multiple rules, the first matched rule will apply. The order of rules is important. -If a request doesn't match any rules, or the matched rule has empty "requires" field, JWT verification is not required. +If a request doesn't match any rules, or the matched rule has empty *requires* field, JWT verification is not required. Config samples: @@ -136,98 +135,57 @@ Config samples: providers: jwt_provider1: issuer: https://example.com - remote_jwks: - http_uri: - uri: https://example.com/.well-known/jwks.json - cluster: example_jwks_cluster - cache_duration: - seconds: 300 - jwt_provider2: - issuer: https://example2.com + audiences: + audience1 local_jwks: inline_string: "PUBLIC-KEY" - from_headers: - - name: x-goog-iap-jwt-assertion rules: - - match - - - - HTTP request is authorized or not. -If the request is deemed unauthorized then the request will be denied normally with 403 (Forbidden) response. -Note that sending additional custom metadata from the authorization service to the upstream, or to the downstream is -also possible. This is explained in more details at :ref:`HTTP filter `. - -.. tip:: - It is recommended that this filter is configured first in the filter chain so that requests are - authorized prior to the rest of filters processing the request. - -The content of the requests that are passed to an authorization service is specified by -:ref:`CheckRequest `. - -.. _config_http_filters_ext_authz_http_configuration: + - match: + prefix: /health + - match: + prefix: /api + requires: + provider_and_audiences: + provider_name: jwt_provider1 + audiences: + api_audience + - match: + prefix: / + requires: + provider_name: jwt_provider1 + + +Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1** with an **audience1** *audience* and inline_string *local_jwks*. The config has three rules. The first rule with prefix **/health** has empty *requires* field, if a request has **/health** path prefix, it doesn't need to do any JWT verification. The second rule has path prefix **/api**, its *requires" is to use **jwt_provider1** with *audiences* override of **api_audience**. If a request has **/api** path prefix, it will use **jwt_provider1** with overrided **api_audience** to verify the JWT. The third rule has capture all prefix of **/**, it will match all requests. Its *requires" is to use **jwt_provider1** to verify JWT. The *rules* are checked on the specified order, the first matched *rule* will be used. In this config, the requests not matched with the first and the second rules will match the last one, most requests will use **jwt_provider1** to verify JWT. -The HTTP filter, using a gRPC/HTTP service, can be configured as follows. You can see all the -configuration options at -:ref:`HTTP filter `. - -Configuration Examples ------------------------------ - -A sample filter configuration for a gRPC authorization server: - -.. code-block:: yaml - - http_filters: - - name: envoy.ext_authz - config: - grpc_service: - envoy_grpc: - cluster_name: ext-authz .. code-block:: yaml - clusters: - - name: ext-authz - type: static - http2_protocol_options: {} - hosts: - - socket_address: { address: 127.0.0.1, port_value: 10003 } - -A sample filter configuration for a raw HTTP authorization server: + providers: + provider1: + issuer: https://provider1.com + local_jwks: + inline_string: "PUBLIC-KEY" + provider2: + issuer: https://provider2.com + local_jwks: + inline_string: "PUBLIC-KEY" + rules: + - match: + prefix: /any + requires: + requires_any: + requirements: + - provider_name: provider1 + - provider_name: provider2 + - match: + prefix: /all + requires: + requires_all: + requirements: + - provider_name: provider1 + - provider_name: provider2 + + +Above config uses *group* requirements. The first *rule* specifies *requires_any*; if any of **provider1** or **provider2** requirement is satisfied, the request is OK to proceed. The second *rule* specifies *requires_all*; only if both **provider1** and **provider2** requirements are satisfied, the request is OK to proceed. -.. code-block:: yaml - http_filters: - - name: envoy.ext_authz - config: - http_service: - server_uri: - uri: 127.0.0.1:10003 - cluster: ext-authz - timeout: 0.25s - failure_mode_allow: false - -.. code-block:: yaml - - clusters: - - name: ext-authz - connect_timeout: 0.25s - type: logical_dns - lb_policy: round_robin - hosts: - - socket_address: { address: 127.0.0.1, port_value: 10003 } - -Statistics ----------- -The HTTP filter outputs statistics in the *cluster..ext_authz.* namespace. - -.. csv-table:: - :header: Name, Type, Description - :widths: 1, 1, 2 - - ok, Counter, Total responses from the filter. - error, Counter, Total errors contacting the external service. - denied, Counter, Total responses from the authorizations service that were to deny the traffic. - failure_mode_allowed, Counter, "Total requests that were error(s) but were allowed through because - of failure_mode_allow set to true." From a0716362924e35a6a2047eeb7d609a8229d6dff5 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 25 Sep 2018 17:34:21 +0000 Subject: [PATCH 08/16] format Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index b60e67433d2b2..13bdeed101431 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -30,7 +30,7 @@ The **default extract location**. If *from_headers* and *from_params* is empty, Authorization: Bearer If fails to extract a JWT from there, then check query parameter key *access_token* as this example:: - + /path?access_token= In the filter config, *providers* a map, to map *provider_name* to a *JwtProvider* message. The *provider_name* has to be unique, it is referred in the *JwtRequirement* message *provider_name* field. @@ -72,7 +72,7 @@ In above example, following cluster **example_jwks_cluster** is needed. name: example_jwks_cluster type: STRICT_DNS hosts: - socket_address: + socket_address: address: example.com portValue: 80 @@ -100,17 +100,17 @@ Above example specifies: * *from_headers*: token will be extracted from HTTP headers as:: jwt-assertion: . - + * *forward*: token will forwarded to upstream * JWT payload will be added to the request header as following format:: x-jwt-payload: base64_encoded(jwt_payload_in_JSON) - + RequirementRule ~~~~~~~~~~~~~~~ -It has two fields: *match* and *requires*. The field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field *requires* specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such forms, such as "require_all" or "require_any". +It has two fields: *match* and *requires*. The field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field *requires* specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such forms, such as "require_all" or "require_any". The field *match* uses following fields to define a match: * one of following path_specifier: *prefix*, *path*, and *regex*. @@ -153,7 +153,6 @@ Config samples: prefix: / requires: provider_name: jwt_provider1 - Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1** with an **audience1** *audience* and inline_string *local_jwks*. The config has three rules. The first rule with prefix **/health** has empty *requires* field, if a request has **/health** path prefix, it doesn't need to do any JWT verification. The second rule has path prefix **/api**, its *requires" is to use **jwt_provider1** with *audiences* override of **api_audience**. If a request has **/api** path prefix, it will use **jwt_provider1** with overrided **api_audience** to verify the JWT. The third rule has capture all prefix of **/**, it will match all requests. Its *requires" is to use **jwt_provider1** to verify JWT. The *rules* are checked on the specified order, the first matched *rule* will be used. In this config, the requests not matched with the first and the second rules will match the last one, most requests will use **jwt_provider1** to verify JWT. @@ -184,8 +183,5 @@ Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1 requirements: - provider_name: provider1 - provider_name: provider2 - Above config uses *group* requirements. The first *rule* specifies *requires_any*; if any of **provider1** or **provider2** requirement is satisfied, the request is OK to proceed. The second *rule* specifies *requires_all*; only if both **provider1** and **provider2** requirements are satisfied, the request is OK to proceed. - - From bc7e01513cf81be650df984cb32f496ebb5005a1 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 25 Sep 2018 22:03:18 +0000 Subject: [PATCH 09/16] update format Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 13bdeed101431..c3ebbaf132495 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -3,17 +3,19 @@ JWT Authentication ================== -This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its signature, expiration time, audiences and issuer. If the JWT verification fails, its request will be rejected. If the JWT verification success, its payload could be forwarded to the upstream for further authorization if desired. JWKS needed to verify JWT signatures can be specified in the filter config or can be fetched remotely from a JWKS server. +This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its signature, expiration time, audiences and issuer. If the JWT verification fails, its request will be rejected. If the JWT verification success, its payload could be forwarded to the upstream for further authorization if desired. + +JWKS is needed to verify JWT signatures. They can be specified in the filter config or can be fetched remotely from a JWKS server. Configuration ------------- -This HTTP filer config has two fields, *providers* and *rules*. Field *providers* specifies how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and where to output its payload. Field *rules* specifies matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be used. +This HTTP :ref:`filer config ` has two fields, *providers* and *rules*. Field *providers* specifies how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and where to output its payload. Field *rules* specifies matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be used. JwtProvider ~~~~~~~~~~~ -It specifies how a JWT should be verified. It has following fields: +:ref:`JwtProvider ` specifies how a JWT should be verified. It has following fields: * *issuer*: the principal that issued the JWT, usually a URL or an email address. * *audiences*: a list of JWT audiences allowed to access. A JWT containing any of these audiences will be accepted. @@ -25,19 +27,23 @@ It specifies how a JWT should be verified. It has following fields: * *from_params*: extract JWT from query parameters. * *forward_payload_header*: forward the JWT payload in the specified HTTP header. -The **default extract location**. If *from_headers* and *from_params* is empty, the default location to extract JWT is from HTTP header:: +Default Extract Location +~~~~~~~~~~~~~~~~~~~~~~~~ + +If *from_headers* and *from_params* is empty, the default location to extract JWT is from HTTP header:: Authorization: Bearer -If fails to extract a JWT from there, then check query parameter key *access_token* as this example:: +If fails to extract a JWT from above header, then check query parameter key *access_token* as this example:: /path?access_token= -In the filter config, *providers* a map, to map *provider_name* to a *JwtProvider* message. The *provider_name* has to be unique, it is referred in the *JwtRequirement* message *provider_name* field. +In the :ref:`filter config `, *providers* is a map, to map *provider_name* to a :ref:`JwtProvider `. The *provider_name* has to be unique, it is referred in the `JwtRequirement ` in its *provider_name* field. -Important note for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the hostname to fetch JWKS is dynamic. +Important note for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup an Envoy cluster for such URL. -Config examples: +Config Examples +~~~~~~~~~~~~~~~ .. code-block:: yaml @@ -49,7 +55,7 @@ Config examples: - bookstore_web.apps.googleusercontent.com remote_jwks: http_uri: - uri: https://example.com/.well-known/jwks.json + uri: https://example.com/jwks.json cluster: example_jwks_cluster cache_duration: seconds: 300 @@ -59,12 +65,12 @@ Above example specifies: * *provider_name* is **provider_name1** * *issuer* is **https://example.com** * *audiences*: **bookstore_android.apps.googleusercontent.com** and **bookstore_web.apps.googleusercontent.com** -* *remote_jwks*: use URL **https://example.com/.well-known/jwks.json** from cluster **example_jwks_cluster**, its cache duration is 300 seconds. +* *remote_jwks*: use URL **https://example.com/jwks.json** from cluster **example_jwks_cluster**, its cache duration is 300 seconds. * token will be extracted from the default extract locations since *from_headers* and *from_params* are empty. * token will not be forwarded to upstream since *forward* is not set, default is **false** * JWT payload will not be added to the request header since *forward_payload_header* is not set. -In above example, following cluster **example_jwks_cluster** is needed. +Following cluster **example_jwks_cluster** is needed to fetch JWKS. .. code-block:: yaml @@ -110,21 +116,23 @@ Above example specifies: RequirementRule ~~~~~~~~~~~~~~~ -It has two fields: *match* and *requires*. The field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field *requires* specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such forms, such as "require_all" or "require_any". +:ref:`RequirementRule ` has two fields: *match* and *requires*. The field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field *requires* specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such complex forms as "require_all" or "require_any". The field *match* uses following fields to define a match: + * one of following path_specifier: *prefix*, *path*, and *regex*. * *headers*: specify how to match HTTP headers. * *query_parameters*: specify how to match query parameters. The field *requires* can be specified as any one of followings: + * *provider_name*: specifies the provider name of required JwtProvider -* *provider_and_audiences*: specifies the provider with audiences. The audiences will override the one in the JwtProvider. +* *provider_and_audiences*: specifies the provider with override audiences. The audiences will override the one specified in the :ref:`JwtProvider `. * *requires_any*: a list of requirements that if any of them success, it will be success. * *requires_all*: a list of requirements that only if all of them success, it will be success. -* *allow_missing_or_failed*: A flag for a special usage. If true, all JWTs will be verified, successfully verified JWTs will output its payload results. The request will proceeded even with some verification failures. The typical use case is: there is another HTTP filter after this filter. This JWT filter is used to do JWT verification, that filter will make decision based on the results. Istio authentication feature is implemented this way. +* *allow_missing_or_failed*: If true, all JWTs will be verified, successfully verified JWTs will output its payload results. The request will proceeded even with any verification failures. The designed use case: another HTTP filter is inserted after this JWT filter. This JWT filter is used to do JWT verification, that filter will make decision based on the payload results outputed from this filter. -If a request matches multiple rules, the first matched rule will apply. The order of rules is important. +If a request matches multiple rules, the first matched rule will apply. The order of rules is important. The suggestion is to put the more specific matching rule first, more boarder matching rule later, and a capture all matching rule at the last. If a request doesn't match any rules, or the matched rule has empty *requires* field, JWT verification is not required. @@ -154,7 +162,13 @@ Config samples: requires: provider_name: jwt_provider1 -Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1** with an **audience1** *audience* and inline_string *local_jwks*. The config has three rules. The first rule with prefix **/health** has empty *requires* field, if a request has **/health** path prefix, it doesn't need to do any JWT verification. The second rule has path prefix **/api**, its *requires" is to use **jwt_provider1** with *audiences* override of **api_audience**. If a request has **/api** path prefix, it will use **jwt_provider1** with overrided **api_audience** to verify the JWT. The third rule has capture all prefix of **/**, it will match all requests. Its *requires" is to use **jwt_provider1** to verify JWT. The *rules* are checked on the specified order, the first matched *rule* will be used. In this config, the requests not matched with the first and the second rules will match the last one, most requests will use **jwt_provider1** to verify JWT. +Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1** with an **audience1** *audience* and inline_string *local_jwks*. + +The config has three rules: + +* The first rule with prefix **/health** has empty *requires* field, if a request has **/health** path prefix, it doesn't need to do any JWT verification. +* The second rule has path prefix **/api**, its *requires" is to use **jwt_provider1** with *audiences* override of **api_audience**. If a request has **/api** path prefix, it will use **jwt_provider1** with overrided **api_audience** to verify the JWT. +* The third rule has a capture all prefix of **/**, it will match all requests. Its *requires" is to use **jwt_provider1** to verify JWT. .. code-block:: yaml @@ -184,4 +198,7 @@ Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1 - provider_name: provider1 - provider_name: provider2 -Above config uses *group* requirements. The first *rule* specifies *requires_any*; if any of **provider1** or **provider2** requirement is satisfied, the request is OK to proceed. The second *rule* specifies *requires_all*; only if both **provider1** and **provider2** requirements are satisfied, the request is OK to proceed. +Above config uses more complex *group* requirements: + +* The first *rule* specifies *requires_any*; if any of **provider1** or **provider2** requirement is satisfied, the request is OK to proceed. +* The second *rule* specifies *requires_all*; only if both **provider1** and **provider2** requirements are satisfied, the request is OK to proceed. From da83130f79ea3ae680697d791427660a73b88c7a Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 25 Sep 2018 22:22:11 +0000 Subject: [PATCH 10/16] update format again Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index c3ebbaf132495..0b537ccd98c60 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -40,10 +40,10 @@ If fails to extract a JWT from above header, then check query parameter key *acc In the :ref:`filter config `, *providers* is a map, to map *provider_name* to a :ref:`JwtProvider `. The *provider_name* has to be unique, it is referred in the `JwtRequirement ` in its *provider_name* field. -Important note for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup an Envoy cluster for such URL. +**Important note** for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. -Config Examples -~~~~~~~~~~~~~~~ +JwtProvider config example one +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: yaml @@ -83,7 +83,10 @@ Following cluster **example_jwks_cluster** is needed to fetch JWKS. portValue: 80 -Here is another config example using inline JWKS: +JwtProvider config example two +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Another config example using inline JWKS: .. code-block:: yaml @@ -112,7 +115,6 @@ Above example specifies: x-jwt-payload: base64_encoded(jwt_payload_in_JSON) - RequirementRule ~~~~~~~~~~~~~~~ @@ -132,11 +134,17 @@ The field *requires* can be specified as any one of followings: * *requires_all*: a list of requirements that only if all of them success, it will be success. * *allow_missing_or_failed*: If true, all JWTs will be verified, successfully verified JWTs will output its payload results. The request will proceeded even with any verification failures. The designed use case: another HTTP filter is inserted after this JWT filter. This JWT filter is used to do JWT verification, that filter will make decision based on the payload results outputed from this filter. -If a request matches multiple rules, the first matched rule will apply. The order of rules is important. The suggestion is to put the more specific matching rule first, more boarder matching rule later, and a capture all matching rule at the last. +Important Match Rules +~~~~~~~~~~~~~~~~~~~~~ + +**If a request matches multiple rules, the first matched rule will apply**. The order of rules is important. The suggestion is to put the more specific matching rule first, more boarder matching rule later, and a capture all matching rule at the last. + +If the matched rule has empty *requires* field, **JWT verification is not required**. -If a request doesn't match any rules, or the matched rule has empty *requires* field, JWT verification is not required. +If a request doesn't match any rules, **JWT verification is not required**. -Config samples: +Config example one +~~~~~~~~~~~~~~~~~~ .. code-block:: yaml @@ -170,6 +178,8 @@ The config has three rules: * The second rule has path prefix **/api**, its *requires" is to use **jwt_provider1** with *audiences* override of **api_audience**. If a request has **/api** path prefix, it will use **jwt_provider1** with overrided **api_audience** to verify the JWT. * The third rule has a capture all prefix of **/**, it will match all requests. Its *requires" is to use **jwt_provider1** to verify JWT. +Config example two +~~~~~~~~~~~~~~~~~~ .. code-block:: yaml From 2ae366c40501f10b12fca52230e56d375ce5a809 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 2 Oct 2018 18:48:15 +0000 Subject: [PATCH 11/16] Update per review Signed-off-by: Wayne Zhang --- .../http/jwt_authn/v2alpha/config.proto | 62 +++++++------- .../http_filters/jwt_authn_filter.rst | 84 ++++++------------- 2 files changed, 58 insertions(+), 88 deletions(-) diff --git a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto index edbc4c7acfa47..6b40026f41567 100644 --- a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto +++ b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto @@ -99,7 +99,7 @@ message JwtProvider { // .. code-block:: yaml // // local_jwks: - // inline_string: "ACADADADADA" + // inline_string: ACADADADADA // envoy.api.v2.core.DataSource local_jwks = 4; } @@ -204,37 +204,37 @@ message ProviderWithAudiences { // # Example 1: not required with an empty message // // # Example 2: require A -// provider_name: "provider-A" +// provider_name: provider-A // // # Example 3: require A or B // requires_any: // requirements: -// - provider_name: "provider-A" -// - provider_name: "provider-B" +// - provider_name: provider-A +// - provider_name: provider-B // // # Example 4: require A and B // requires_all: // requirements: -// - provider_name: "provider-A" -// - provider_name: "provider-B" +// - provider_name: provider-A +// - provider_name: provider-B // // # Example 5: require A and (B or C) // requires_all: // requirements: -// - provider_name: "provider-A" +// - provider_name: provider-A // - requires_any: // requirements: -// - provider_name: "provider-B" -// - provider_name: "provider-C" +// - provider_name: provider-B +// - provider_name: provider-C // // # Example 6: require A or (B and C) // requires_any: // requirements: -// - provider_name: "provider-A" +// - provider_name: provider-A // - requires_all: // requirements: -// - provider_name: "provider-B" -// - provider_name: "provider-C" +// - provider_name: provider-B +// - provider_name: provider-C // message JwtRequirement { oneof requires_type { @@ -280,7 +280,7 @@ message JwtRequirementAndList { // .. code-block:: yaml // // - match: -// prefix: "/healthz" +// prefix: /healthz // // In above example, "requires" field is empty for /healthz prefix match, // it means that requests matching the path prefix don't require JWT authentication. @@ -290,8 +290,8 @@ message JwtRequirementAndList { // .. code-block:: yaml // // - match: -// prefix: "/" -// requires: { provider_name: "provider-A" } +// prefix: / +// requires: { provider_name: provider-A } // // In above example, all requests matched the path prefix require jwt authentication // from "provider-A". @@ -304,7 +304,7 @@ message RequirementRule { // .. code-block:: yaml // // match: - // prefix: "/" + // prefix: / // envoy.api.v2.route.RouteMatch match = 1 [(validate.rules).message.required = true]; @@ -336,22 +336,22 @@ message RequirementRule { // rules: // # Not jwt verification is required for /health path // - match: -// prefix: "/health" +// prefix: /health // // # Jwt verification for provider1 is required for path prefixed with "prefix" // - match: -// prefix: "/prefix" +// prefix: /prefix // requires: -// provider_name: "provider1" +// provider_name: provider1 // // # Jwt verification for either provider1 or provider2 is required for all other requests. // - match: -// prefix: "/" +// prefix: / // requires: // requires_any: // requirements: -// - provider_name: "provider1" -// - provider_name: "provider2" +// - provider_name: provider1 +// - provider_name: provider2 // message JwtAuthentication { // Map of provider names to JwtProviders. @@ -384,25 +384,25 @@ message JwtAuthentication { // // rules: // - match: - // prefix: "/healthz" + // prefix: /healthz // - match: - // prefix: "/baz" + // prefix: /baz // requires: - // provider_name: "provider1" + // provider_name: provider1 // - match: - // prefix: "/foo" + // prefix: /foo // requires: // requires_any: // requirements: - // - provider_name: "provider1" - // - provider_name: "provider2" + // - provider_name: provider1 + // - provider_name: provider2 // - match: - // prefix: "/bar" + // prefix: /bar // requires: // requires_all: // requirements: - // - provider_name: "provider1" - // - provider_name: "provider2" + // - provider_name: provider1 + // - provider_name: provider2 // repeated RequirementRule rules = 2; } diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 0b537ccd98c60..fce8fe319bddf 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -3,23 +3,26 @@ JWT Authentication ================== -This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its signature, expiration time, audiences and issuer. If the JWT verification fails, its request will be rejected. If the JWT verification success, its payload could be forwarded to the upstream for further authorization if desired. +This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its signature, audiences and issuer. It will also check its time restrictions, such as expiration and nbf (not before) time. If the JWT verification fails, its request will be rejected. If the JWT verification succeeds, its payload can be forwarded to the upstream for further authorization if desired. JWKS is needed to verify JWT signatures. They can be specified in the filter config or can be fetched remotely from a JWKS server. Configuration ------------- -This HTTP :ref:`filer config ` has two fields, *providers* and *rules*. Field *providers* specifies how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and where to output its payload. Field *rules* specifies matching rules and their requirements. It a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be used. +This HTTP :ref:`filter config ` has two fields: + +* Field *providers* specifies how a JWT should be verified, such as where to extract the token, where to fetch the public key (JWKS) and where to output its payload. +* Field *rules* specifies matching rules and their requirements. If a request matches a rule, its requirement applies. The requirement specifies which JWT providers should be used. JwtProvider ~~~~~~~~~~~ -:ref:`JwtProvider ` specifies how a JWT should be verified. It has following fields: +:ref:`JwtProvider ` specifies how a JWT should be verified. It has the following fields: * *issuer*: the principal that issued the JWT, usually a URL or an email address. * *audiences*: a list of JWT audiences allowed to access. A JWT containing any of these audiences will be accepted. - If not specified, will not check audiences in the JWT. + If not specified, the audiences in JWT will not be checked. * *local_jwks*: fetch JWKS in local data source, either in a local file or embedded in the inline string. * *remote_jwks*: fetch JWKS from a remote HTTP server, also specify cache duration. * *forward*: if true, JWT will be forwarded to the upstream. @@ -34,16 +37,16 @@ If *from_headers* and *from_params* is empty, the default location to extract J Authorization: Bearer -If fails to extract a JWT from above header, then check query parameter key *access_token* as this example:: +If fails to extract a JWT from above header, then check query parameter key *access_token* as in this example:: /path?access_token= -In the :ref:`filter config `, *providers* is a map, to map *provider_name* to a :ref:`JwtProvider `. The *provider_name* has to be unique, it is referred in the `JwtRequirement ` in its *provider_name* field. +In the :ref:`filter config `, *providers* is a map, to map *provider_name* to a :ref:`JwtProvider `. The *provider_name* must be unique, it is referred in the `JwtRequirement ` in its *provider_name* field. **Important note** for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. -JwtProvider config example one -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Remote JWKS config example +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: yaml @@ -60,15 +63,7 @@ JwtProvider config example one cache_duration: seconds: 300 -Above example specifies: - -* *provider_name* is **provider_name1** -* *issuer* is **https://example.com** -* *audiences*: **bookstore_android.apps.googleusercontent.com** and **bookstore_web.apps.googleusercontent.com** -* *remote_jwks*: use URL **https://example.com/jwks.json** from cluster **example_jwks_cluster**, its cache duration is 300 seconds. -* token will be extracted from the default extract locations since *from_headers* and *from_params* are empty. -* token will not be forwarded to upstream since *forward* is not set, default is **false** -* JWT payload will not be added to the request header since *forward_payload_header* is not set. +Above example fetches JWSK from a remote server with URL https://example.com/jwks.json. The token will be extracted from the default extract locations. The token will not be forwarded to upstream. JWT payload will not be added to the request header. Following cluster **example_jwks_cluster** is needed to fetch JWKS. @@ -83,8 +78,8 @@ Following cluster **example_jwks_cluster** is needed to fetch JWKS. portValue: 80 -JwtProvider config example two -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Inline JWKS config example +~~~~~~~~~~~~~~~~~~~~~~~~~~ Another config example using inline JWKS: @@ -100,51 +95,32 @@ Another config example using inline JWKS: forward: true forward_payload_header: x-jwt-payload -Above example specifies: - -* *provider_name* is **provider_name2** -* *issuer* is **https://example2.com** -* *audiences*: not specified, JWT *aud* field will not be checked. -* *local_jwks*: JWKS is embeded in the inline string. -* *from_headers*: token will be extracted from HTTP headers as:: +Above example uses config inline string to specify JWKS. The JWT token will be extracted from HTTP headers as:: jwt-assertion: . -* *forward*: token will forwarded to upstream -* JWT payload will be added to the request header as following format:: +JWT payload will be added to the request header as following format:: x-jwt-payload: base64_encoded(jwt_payload_in_JSON) RequirementRule ~~~~~~~~~~~~~~~ -:ref:`RequirementRule ` has two fields: *match* and *requires*. The field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. The field *requires* specifies the JWT requirement, e.g. which provider is required. Multiple providers may be required in such complex forms as "require_all" or "require_any". - -The field *match* uses following fields to define a match: - -* one of following path_specifier: *prefix*, *path*, and *regex*. -* *headers*: specify how to match HTTP headers. -* *query_parameters*: specify how to match query parameters. +:ref:`RequirementRule ` has two fields: -The field *requires* can be specified as any one of followings: +* Field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. +* Field *requires* specifies the JWT requirement, e.g. which provider is required. -* *provider_name*: specifies the provider name of required JwtProvider -* *provider_and_audiences*: specifies the provider with override audiences. The audiences will override the one specified in the :ref:`JwtProvider `. -* *requires_any*: a list of requirements that if any of them success, it will be success. -* *requires_all*: a list of requirements that only if all of them success, it will be success. -* *allow_missing_or_failed*: If true, all JWTs will be verified, successfully verified JWTs will output its payload results. The request will proceeded even with any verification failures. The designed use case: another HTTP filter is inserted after this JWT filter. This JWT filter is used to do JWT verification, that filter will make decision based on the payload results outputed from this filter. +**Important notes:** -Important Match Rules -~~~~~~~~~~~~~~~~~~~~~ - -**If a request matches multiple rules, the first matched rule will apply**. The order of rules is important. The suggestion is to put the more specific matching rule first, more boarder matching rule later, and a capture all matching rule at the last. +**If a request matches multiple rules, the first matched rule will apply**. If the matched rule has empty *requires* field, **JWT verification is not required**. If a request doesn't match any rules, **JWT verification is not required**. -Config example one -~~~~~~~~~~~~~~~~~~ +Single requirement config example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: yaml @@ -154,7 +130,7 @@ Config example one audiences: audience1 local_jwks: - inline_string: "PUBLIC-KEY" + inline_string: PUBLIC-KEY rules: - match: prefix: /health @@ -170,16 +146,10 @@ Config example one requires: provider_name: jwt_provider1 -Above config specifies one *JwtProvider* with *provider_name* as **jwt_provider1** with an **audience1** *audience* and inline_string *local_jwks*. - -The config has three rules: - -* The first rule with prefix **/health** has empty *requires* field, if a request has **/health** path prefix, it doesn't need to do any JWT verification. -* The second rule has path prefix **/api**, its *requires" is to use **jwt_provider1** with *audiences* override of **api_audience**. If a request has **/api** path prefix, it will use **jwt_provider1** with overrided **api_audience** to verify the JWT. -* The third rule has a capture all prefix of **/**, it will match all requests. Its *requires" is to use **jwt_provider1** to verify JWT. +Above config uses single requirement rule, each rule may have either an empty requirement or a single requirement with one provider name. -Config example two -~~~~~~~~~~~~~~~~~~ +Group requirement config example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: yaml From 197f29700ee05ccc6aa2c13b85211df7d0f181f3 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 2 Oct 2018 18:54:23 +0000 Subject: [PATCH 12/16] remove double quote Signed-off-by: Wayne Zhang --- docs/root/configuration/http_filters/jwt_authn_filter.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index fce8fe319bddf..24da5b4105930 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -89,7 +89,7 @@ Another config example using inline JWKS: provider_name2: issuer: https://example2.com local_jwks: - inline_string: "PUBLIC-KEY" + inline_string: PUBLIC-KEY from_headers: - name: jwt-assertion forward: true @@ -157,11 +157,11 @@ Group requirement config example provider1: issuer: https://provider1.com local_jwks: - inline_string: "PUBLIC-KEY" + inline_string: PUBLIC-KEY provider2: issuer: https://provider2.com local_jwks: - inline_string: "PUBLIC-KEY" + inline_string: PUBLIC-KEY rules: - match: prefix: /any From 1549260cd2ea3df25187d536e218daff5c8cca28 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 2 Oct 2018 22:00:36 +0000 Subject: [PATCH 13/16] use attention rst Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 24da5b4105930..eaaf91f10171a 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -7,6 +7,9 @@ This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its JWKS is needed to verify JWT signatures. They can be specified in the filter config or can be fetched remotely from a JWKS server. +.. Supported JWT alg:: + Only ES256 and RS256 are supported! + Configuration ------------- @@ -43,7 +46,10 @@ If fails to extract a JWT from above header, then check query parameter key *acc In the :ref:`filter config `, *providers* is a map, to map *provider_name* to a :ref:`JwtProvider `. The *provider_name* must be unique, it is referred in the `JwtRequirement ` in its *provider_name* field. -**Important note** for *remote_jwks*, a **jwks_cluster** cluster is required for Envoy to talk to a JWKS server. Due to this, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. +.. Important note:: + For *remote_jwks*, a **jwks_cluster** cluster is required. + +Due to above requirement, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. Remote JWKS config example ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -111,13 +117,12 @@ RequirementRule * Field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. * Field *requires* specifies the JWT requirement, e.g. which provider is required. -**Important notes:** - -**If a request matches multiple rules, the first matched rule will apply**. - -If the matched rule has empty *requires* field, **JWT verification is not required**. +.. Important notes:: + **If a request matches multiple rules, the first matched rule will apply**. + + If the matched rule has empty *requires* field, **JWT verification is not required**. -If a request doesn't match any rules, **JWT verification is not required**. + If a request doesn't match any rules, **JWT verification is not required**. Single requirement config example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From aeec5f33fe79be84ba44a2c3df7aa4d49b1977c0 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Tue, 2 Oct 2018 22:10:35 +0000 Subject: [PATCH 14/16] fix annotation usage error Signed-off-by: Wayne Zhang --- .../http_filters/jwt_authn_filter.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index eaaf91f10171a..4a2b0e9da608d 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -7,8 +7,8 @@ This HTTP filter can be used to verify JSON Web Token (JWT). It will verify its JWKS is needed to verify JWT signatures. They can be specified in the filter config or can be fetched remotely from a JWKS server. -.. Supported JWT alg:: - Only ES256 and RS256 are supported! +.. attention:: + Only ES256 and RS256 are supported for the JWT alg. Configuration ------------- @@ -46,7 +46,7 @@ If fails to extract a JWT from above header, then check query parameter key *acc In the :ref:`filter config `, *providers* is a map, to map *provider_name* to a :ref:`JwtProvider `. The *provider_name* must be unique, it is referred in the `JwtRequirement ` in its *provider_name* field. -.. Important note:: +.. important:: For *remote_jwks*, a **jwks_cluster** cluster is required. Due to above requirement, `OpenID connection discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. @@ -117,12 +117,10 @@ RequirementRule * Field *match* specifies how a request can be matched; e.g. by HTTP headers, or by query parameters, or by path prefixes. * Field *requires* specifies the JWT requirement, e.g. which provider is required. -.. Important notes:: - **If a request matches multiple rules, the first matched rule will apply**. - - If the matched rule has empty *requires* field, **JWT verification is not required**. - - If a request doesn't match any rules, **JWT verification is not required**. +.. important:: + - **If a request matches multiple rules, the first matched rule will apply**. + - If the matched rule has empty *requires* field, **JWT verification is not required**. + - If a request doesn't match any rules, **JWT verification is not required**. Single requirement config example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 8994580833dba54f2f13b22c9a1f8f46c95b0189 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Wed, 3 Oct 2018 16:24:27 +0000 Subject: [PATCH 15/16] update link titles Signed-off-by: Wayne Zhang --- api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto | 6 +++--- docs/root/configuration/http_filters/jwt_authn_filter.rst | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto index 6b40026f41567..153264e4f1242 100644 --- a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto +++ b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto @@ -13,9 +13,9 @@ import "validate/validate.proto"; // Please see following for JWT authentication flow: // -// * `JWT format `_ -// * `OAuth2.0 `_ -// * `OIDC1.0 `_ +// * `JSON Web Token (JWT) `_ +// * `The OAuth 2.0 Authorization Framework `_ +// * `OpenID Connect `_ // // A JwtProvider message specifies how a JSON Web Token (JWT) can be verified. It specifies: // diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 4a2b0e9da608d..2b74c22cd1ed5 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -81,7 +81,7 @@ Following cluster **example_jwks_cluster** is needed to fetch JWKS. hosts: socket_address: address: example.com - portValue: 80 + port_value: 80 Inline JWKS config example From 3a983565cae66963380cbd1b3d8e64998846a9e1 Mon Sep 17 00:00:00 2001 From: Wayne Zhang Date: Wed, 3 Oct 2018 17:13:22 +0000 Subject: [PATCH 16/16] update another link title Signed-off-by: Wayne Zhang --- docs/root/configuration/http_filters/jwt_authn_filter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/root/configuration/http_filters/jwt_authn_filter.rst b/docs/root/configuration/http_filters/jwt_authn_filter.rst index 2b74c22cd1ed5..1e22742e9f7b5 100644 --- a/docs/root/configuration/http_filters/jwt_authn_filter.rst +++ b/docs/root/configuration/http_filters/jwt_authn_filter.rst @@ -49,7 +49,7 @@ In the :ref:`filter config `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. +Due to above requirement, `OpenID Connect Discovery `_ is not supported since the URL to fetch JWKS is in the response of the discovery. It is not easy to setup a cluster config for a dynamic URL. Remote JWKS config example ~~~~~~~~~~~~~~~~~~~~~~~~~~