profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/yangminzhu/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Yangmin Zhu yangminzhu Google Software Engineer

istio-ecosystem/security-policy-migrate 1

A tool to convert the Istio v1alpha1 authentication policy to the v1beta1 version.

dengyijia/envoy-wasm 0

Playground for Envoy WASM filter

yangminzhu/api 0

API, config definitions and standard vocabulary definitions for the Istio project

yangminzhu/blog-examples 0

Sample code and files from StackRox blog posts

yangminzhu/build-your-own-x 0

🤓 Build your own (insert technology here)

yangminzhu/cel 0

CEL expression playground

yangminzhu/cel-cpp 0

Common Expression Language -- C++ implementations

PullRequestReviewEvent

Pull request review commentistio/istio

Add downstream SAN to access logs

 const ( 		"%DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" " + 		"\"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" " + 		"%UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% " +-		"%DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%\n"+		"%DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %DOWNSTREAM_PEER_URI_SAN% %ROUTE_NAME%\n"

Is the current REQUESTED_SERVER_NAME enough for telling the mTLS status or maybe DOWNSTREAM_TLS_VERSION is better as it is more straightforward and covers both TLS and mTLS?

DOWNSTREAM_PEER_URI_SAN is also fine to me as it gives more information that can be useful in general debugging.

Either way, please also remember to update the documentation of the default access log: https://istio.io/latest/docs/tasks/observability/logs/access-log/#default-access-log-format

howardjohn

comment created time in a day

PullRequestReviewEvent

pull request commentistio/api

support x-jwt-claim in virtual service

@istio/technical-oversight-committee please take a look, thanks.

yangminzhu

comment created time in a day

pull request commentistio/api

support x-jwt-claim in virtual service

How about not making any change except mentioning that VirtualService may route using metadata. VirtualService is beta, x-jwt-claim is at best alpha - not a good idea to confuse users to believe this scheme is at beta stability and won't change. Also keep in mind that the VirtualService API - and it's K8S-Gateway/HttpRoute replacement - are not tied to envoy, we support at least proxyless. Maybe x-jwt-claim will move to beta at some point, maybe will change based on feedback and making it consistent with mTLS claims.

@costinm I'm very confused by your comment. Can you clarify what you mean by not making any change except mentioning that VirtualServie may route using metadata? Isn't that's what the PR already doing? We're not changing the VirtualService CRD schema because we reuse the header field with a special key x-jwt-claim. This PR just adds the comment to mention it.

I'm not too worried about the alpha/beta thing, we can clarify it in the doc and API, the virtual service API itself is still using v1alpha1 API version.

We also shouldn't mention metadata because that's internal implementation detail in the data plane, different client may implement the support in a different way, for example, proxyless does not support metadata today.

yangminzhu

comment created time in 2 days

Pull request review commentistio/api

support x-jwt-claim in virtual service

 message HTTPMatchRequest {   //   // - `regex: "value"` for RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).   //-  // If the value is empty and only the name of header is specfied, presence of the header is checked.-  // **Note:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.+  // If the value is empty and only the name of header is specified, presence of the header is checked.+  // **Note 1:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.+  //+  // **Note 2:** The special key `x-jwt-claim` is reserved for matching with JWT claims on ingress gateway.+  // Claim of type string or list of string is supported. Nested claims is also supported using the separator "." or "-"

@howardjohn I just updated to use only . as the separator, PTAL. This won't work for 100% customers but should be good for most users and significantly simplify the API. I think we can iterate to support the corner cases (e.g. claim name with .) later.

yangminzhu

comment created time in 2 days

PullRequestReviewEvent

push eventyangminzhu/api

Yangmin Zhu

commit sha 4d2063fb348629876740ab77c6a3af58b9ef6f64

update

view details

push time in 2 days

pull request commentistio/api

support x-jwt-claim in virtual service

It is fine to iterate on a feature - provide a basic feature first, get feedback and resolve the problem for some customers. It is also fine if some customers and use cases can't be satisfied - if other products provide such feature they can use them as well. Or use WASM, EnvoyFilters, etc. Having an API that is too complex or tries to solve all problems is usually bad for everyone, in particular for security where complexity almost always results in security bugs. Keep in mind all this needs tests, docs, etc - it is much better to take small iterative steps.

Nested claims is a common and pretty basic use case and not even close to the "all problem" statement.

To start with a simpler API, we can support the . as the separator: x-jwt-claim.key1 and x-jwt-claim.key1.key2 are both very natural formats, there is no extra complexity to support nested claim at all. It won't work for claim name with . but we can figure it out in later iterations.

yangminzhu

comment created time in 2 days

pull request commentistio/api

support x-jwt-claim in virtual service

Or: for the first iteration just support the common/standard claims, which are simpler ( aud, iss, etc).

@costinm there are many non standard claims we need support (e.g. group, groups, etc.), I think we just don't need to restrict the claim name here.

Regarding nested claims, it's actually common and can be found in JWT issued by many identity provider, the same feature was asked by many users for the authorization policy before. I'm just afraid that it may block the adoption for some customers without the nested claim support.

yangminzhu

comment created time in 3 days

Pull request review commentistio/api

support x-jwt-claim in virtual service

 message HTTPMatchRequest {   //   // - `regex: "value"` for RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).   //-  // If the value is empty and only the name of header is specfied, presence of the header is checked.-  // **Note:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.+  // If the value is empty and only the name of header is specified, presence of the header is checked.+  // **Note 1:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.+  //+  // **Note 2:** The special key `x-jwt-claim` is reserved for matching with JWT claims on ingress gateway.+  // Claim of type string or list of string is supported. Nested claims is also supported using the separator "." or "-"

I think the options are not to make the separator dynamic but just to define multiple (more than 1) separators, dynamic means the separator is changing according to the actual claim name but here it's fixed in the config.

Also some other options:

option 4: use a much less common character as separator, for example, & (or one of the characther in !#$%&'*+|~), x-jwt-claim&key1&key2. It's likely good enough for practical use cases. (for example, the authorization policy uses the syntax request.auth.claims[key1][key2]... for nested claims but I don't think it ever cause problems for customers even if the claim name could technically include [ or ])

option 5: use a more special syntax like x-jwt-claim[key1][key2] (same syntax as the current authorization policy for jwt claim matching). However, the [ and ] is not valid in HTTP header name and will not pass the regex validation of the header name in the gateway-api

option 6: make it configurable, it's then another problem of where to configure it: annotation in virtual service, environmental variable on istiod, a new field in config map, etc.

option 7: support escape syntax, for example, if use \ as the escape character. x-jwt-claim-key\-1-another\-key will match with claims key-1 and another-key.

yangminzhu

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentistio/api

support x-jwt-claim in virtual service

 message HTTPMatchRequest {   //   // - `regex: "value"` for RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).   //-  // If the value is empty and only the name of header is specfied, presence of the header is checked.-  // **Note:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.+  // If the value is empty and only the name of header is specified, presence of the header is checked.+  // **Note 1:** The keys `uri`, `scheme`, `method`, and `authority` will be ignored.+  //+  // **Note 2:** The special key `x-jwt-claim` is reserved for matching with JWT claims on ingress gateway.+  // Claim of type string or list of string is supported. Nested claims is also supported using the separator "." or "-"

The . and - together should be good for 99% claim names in JWT token.

If we want to support the case when both . and - is used in JWT token, we could consider:

option 1: Support more allowed special characters ("!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "" / "|" / "~"` defined in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6) for valid separator.

option 2: Support all characters (including those not allowed in header name) to be used as claim separator.

option 3: add a dedicated jwt claim field in virtual service instead of reusing the header field. This has been discussed in the design doc and is not favored by the networking WG as it makes it harder to align with the new gateway-api in the future.

cc @howardjohn @mandarjog @costinm @louiscryan

yangminzhu

comment created time in 3 days

PullRequestReviewEvent

PR opened istio/api

support x-jwt-claim in virtual service

Update the virtual service API for the support of x-jwt-claim, no CRD changes, reuse the headers field.

Design doc: https://docs.google.com/document/d/1s8Lykf8-KUZTLiG4YMSCHvxBDwZzHlrrHyZ7cJymc_8/edit#heading=h.6p29w9kcduab

+101 -21

0 comment

5 changed files

pr created time in 3 days

create barnchyangminzhu/api

branch : jwt-route

created branch time in 3 days

issue commentistio/istio

envoyExtAuthzHttp does case-sensitive matching on headers

yeah, I think we can just make it case insensitive by default to conform to the spec, @sunbit will you be able take this issue? should be a simple change, let me know if you need any help, thanks.

sunbit

comment created time in 4 days

Pull request review commentistio/istio

support routing based on jwt claims

 func isCatchAllHeaderMatch(in *networking.StringMatch) bool { 	return catchall } +// translateMetadataMatch translates a header match to dynamic metadata matcher. Returns nil if the header is not supported+// or the header format is invalid for generating metadata matcher.+//+// The currently only supported header is x-jwt-claim for JWT claims matching. Nested claims is also supported using+// the separator "." or "-" between claim names. For example,

This is not ideal if if we can avoid it... is there any character that is a valid HTTP header but not a jwt claim? I am guessing no because claim can be any json key?

yeah, I don't think there would be any character that is valid in HTTP but not in jwt, it's actually the other way, you can technically put anything in the jwt claim (but practically it's mostly only ASCII characters).

I feel like:

  • Have 1 separator handles 99% of cases
  • Have 2 separators handles 99.5% of cases but doubles the complexity

For example, if my claim is "foo-bar.com" it would not work.

Maybe an alternative is to have users URL encode any .s?

I think . and - addresses the most common use cases (99.5%), Is the complexity mainly for user to understand there are 2 options for the separator? (it does not add too much complexity in implementation). I'm not sure if supporting URL encode in header is a good idea, AFAIK the header is not supposed to be url encoded.

The other alternative is probably just to support all valid header characters (except ALPHA and DIGIT, see the tchar definition in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6) as the separator, this is a bit similar to the multiple delimiter usage in the linux command sed.

@costinm @mandarjog any thoughts on this?

yangminzhu

comment created time in 4 days

PullRequestReviewEvent

pull request commentenvoyproxy/envoy

jwt_authn: Add header_to_metadata

@qiwzhang @yangminzhu I have a question, re:

https://github.com/envoyproxy/envoy/blob/a3cc673ccc6f2c42d92d63de11b1aa781c5f991d/source/extensions/filters/http/jwt_authn/verifier.h#L29-L34

. Do you think this is still correct? I'm not sure I understand there is a use-case when we do this (storing the payload as a string).

storing the payload as a string is to pass the payload to backend application without the signature so that the backend can not reuse the JWT token.

dio

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentenvoyproxy/envoy

jwt_authn: Add header_to_metadata

 message JwtProvider {   //   string payload_in_metadata = 9; +  // If non empty, similar to :ref:`payload <envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtProvider.payload_in_metadata>`,+  // a successfully verified JWT header will be written to :ref:`Dynamic State <arch_overview_data_sharing_between_filters>`+  // as an entry (``protobuf::Struct``) in **envoy.filters.http.jwt_authn** *namespace* with the+  // value of this field as the key.+  //+  // For example, if ``header_in_metadata`` is *my_header*:+  //+  // .. code-block:: yaml+  //+  //   envoy.filters.http.jwt_authn:+  //     my_header:+  //       alg: JWT+  //       kid: EF71iSaosbC5C4tC6Syq1Gm647M+  //       alg: PS256+  //+  // When the metadata has **envoy.filters.http.jwt_authn** entry already (for example if+  // :ref:`payload_in_metadata <envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtProvider.payload_in_metadata>`+  // is not empty), it will be inserted as a new entry in the same *namespace* as shown below:+  //+  // .. code-block:: yaml+  //+  //   envoy.filters.http.jwt_authn:+  //     my_payload:+  //       iss: https://example.com+  //       sub: test@example.com+  //       aud: https://example.com+  //       exp: 1501281058+  //     my_header:+  //       alg: JWT+  //       kid: EF71iSaosbC5C4tC6Syq1Gm647M+  //       alg: PS256+  //+  string header_in_metadata = 14;

hmm, the current comment says ... is not allowed ... which I would expect the validation is going to reject the config, or you can just update the comment to be more accurate (it's not suggested due to potential override but can still be used (won't be rejected in validation) if the user is sure it won't have any override for their use case).

dio

comment created time in 8 days

Pull request review commentenvoyproxy/envoy

jwt_authn: Add header_to_metadata

 class AuthenticatorImpl : public Logger::Loggable<Logger::Id::jwt>,   Http::HeaderMap* headers_{};   // The active span for the request   Tracing::Span* parent_span_{&Tracing::NullSpan::instance()};-  // the callback function to set payload+  // The callback function called to set the extracted payload and header from a verified JWT.

set_payload_cb_ should have a more generic name as it now sets both payload and header.

dio

comment created time in 8 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentenvoyproxy/envoy

jwt_authn: Add header_to_metadata

 message JwtProvider {   //   string payload_in_metadata = 9; +  // If non empty, similar to :ref:`payload <envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtProvider.payload_in_metadata>`,+  // a successfully verified JWT header will be written to :ref:`Dynamic State <arch_overview_data_sharing_between_filters>`+  // as an entry (``protobuf::Struct``) in **envoy.filters.http.jwt_authn** *namespace* with the+  // value of this field as the key.+  //+  // For example, if ``header_in_metadata`` is *my_header*:+  //+  // .. code-block:: yaml+  //+  //   envoy.filters.http.jwt_authn:+  //     my_header:+  //       alg: JWT+  //       kid: EF71iSaosbC5C4tC6Syq1Gm647M+  //       alg: PS256+  //+  // When the metadata has **envoy.filters.http.jwt_authn** entry already (for example if+  // :ref:`payload_in_metadata <envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtProvider.payload_in_metadata>`+  // is not empty), it will be inserted as a new entry in the same *namespace* as shown below:+  //+  // .. code-block:: yaml+  //+  //   envoy.filters.http.jwt_authn:+  //     my_payload:+  //       iss: https://example.com+  //       sub: test@example.com+  //       aud: https://example.com+  //       exp: 1501281058+  //     my_header:+  //       alg: JWT+  //       kid: EF71iSaosbC5C4tC6Syq1Gm647M+  //       alg: PS256+  //+  string header_in_metadata = 14;

what if payload_in_metadata is the same as header_in_metadata? Is it allowed?

dio

comment created time in 8 days

Pull request review commentenvoyproxy/envoy

jwt_authn: Add header_to_metadata

 message JwtProvider {   //   string payload_in_metadata = 9; +  // If non empty, similar to :ref:`payload <envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtProvider.payload_in_metadata>`,

payload -> payload_in_metadata

dio

comment created time in 8 days

PullRequestReviewEvent
PullRequestReviewEvent

issue commentistio/istio

Customized Error response in case of origin authentication failure

Hey, I'm also very interested in this feature - or about current possible workarounds. @bburky did you get it to work with istio local reply? I'm also unsure how to configure this in istio, and would be interested in a workaround that would currently work.

For now you can use the following workaround, you can change 403 to 401 to make it work for JWT authentication fail response:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: customize-authz-response
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
    patch:
      operation: MERGE
      value:
        typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
          local_reply_config:
            mappers:
            - filter:
                # Better to use the metadata_filter to only match the 403 returned by RBAC filter instead of upstream backend.
                status_code_filter:
                  comparison:
                    op: EQ
                    value:
                      default_value: 403
                      runtime_key: placeholder
              status_code: 403
              body:
                inline_string: customized_authz_deny_response
              body_format_override:
                text_format: "<h1>%LOCAL_REPLY_BODY% %RESPONSE_CODE% %REQ(:path)%</h1>"
                content_type: "text/html; charset=UTF-8"
EOF
ahmadsayed

comment created time in 8 days