Skip to content

api: HTTP header and method based authz#5310

Merged
zhaohuabing merged 10 commits intoenvoyproxy:mainfrom
zhaohuabing:authz-api
Feb 23, 2025
Merged

api: HTTP header and method based authz#5310
zhaohuabing merged 10 commits intoenvoyproxy:mainfrom
zhaohuabing:authz-api

Conversation

@zhaohuabing
Copy link
Copy Markdown
Member

API for #4660 and #4661

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
@zhaohuabing zhaohuabing requested a review from a team as a code owner February 19, 2025 02:16
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 19, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 64.94%. Comparing base (f8c0b32) to head (5e2e43a).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5310      +/-   ##
==========================================
- Coverage   64.98%   64.94%   -0.04%     
==========================================
  Files         213      213              
  Lines       33474    33474              
==========================================
- Hits        21752    21740      -12     
- Misses      10396    10403       +7     
- Partials     1326     1331       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@zhaohuabing zhaohuabing changed the title API for HTTP header and method based Authz API for HTTP header and method based authz Feb 19, 2025
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
// +optional
JWT *JWTPrincipal `json:"jwt,omitempty"`

// Headers authorize the request based on the headers in the request.
Copy link
Copy Markdown
Contributor

@arkodg arkodg Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious why we are choosing AND here
OR fits here better

or maybe we can't use HeaderMatch here and may need some other type

here is the use case, id like to deny traffic when x-geoip-country contains foo or bar
so maybe

headers:
- name: x-geoip-country
   values:
   - "foo"
   - "bar"  

fits better here
cc @nezdolik

Copy link
Copy Markdown
Member Author

@zhaohuabing zhaohuabing Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OR can be easily achieved with separate rules, but there is no good way to implement AND expect here. This approach also aligns with the Gateway API HTTPRouteMatch behavior, where multiple HTTPHeaderMatch are ANDed together.

For example, a common use case is setting the default action to Deny while allowing requests from John and Alice in the sales apartment.

    authorization:
      defaultAction: Deny
      rules:
      - action: Allow
        principal:
          headers:
          - name: x-user-id
            value: john
          - name: x-org-id
            value: sales
      - action: Allow
        principal:
          headers:
          - name: x-user-id
            value: alice
          - name: x-org-id
            value: sales

For the use case in your comment:

    authorization:
      defaultAction: Allow
      rules:
      - action: Deny
        principal:
          headers:
          - name: x-geoip-country
            value: foo
      - action: Deny
        principal:
          headers:
          - name: x-geoip-country
            value: bar

One potential concern of this approach is that the rules could be a long list if there are many countries, but if we move OR logic into the headers, the headers can also be lengthy, so there is no fundamental difference between these two approaches.

We could also make header match highly flexibl, allowing expressing logic such as ((foo == bar || foo1 == bar1) && foo2 == bar2). However, this would significantly increase UI complexity. It would not be intuiative for end users, as there would be too many layers of condition combinations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    authorization:
      defaultAction: Allow
      rules:
      - action: Deny
        principal:
          headers:
          - name: x-geoip-country
            value: foo
      - action: Deny
        principal:
          headers:
          - name: x-geoip-country
            value: bar

is too lengthy, the common case is there will be hundreds of such entries, which requires 5x more lines

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your previous example could be reduced to

    authorization:
      defaultAction: Deny
      rules:
      - action: Allow
        principal:
          headers:
          - name: x-user-id
            values:
            - alice
            - john
          - name: x-org-id
            values: 
            - sales

Copy link
Copy Markdown
Member Author

@zhaohuabing zhaohuabing Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, you're right! I was blind by trying to reuse the exiting HeaderMatch, instead, an array should be used for header value:

    authorization:
      defaultAction: Deny
      rules:
      - action: Allow
        principal:
          headers:
          - name: x-user-id
            values: [john, alice]
          - name: x-org-id
            values: sales
    authorization:
      defaultAction: Allow
      rules:
      - action: Deny
        principal:
          headers:
          - name: x-geoip-country
            values: [foo, bar, ...]

This is similar to what we have done for JWT:

        principal:
          jwt:
            provider: example1
            scopes: [foo, bar]

// +optional
// +kubebuilder:validation:MinItems=1
// +notImplementedHide
Methods []gwapiv1.HTTPMethod `json:"methods,omitempty"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should methods live in the top level outside principal because its falls under actions / operation performed by the principal

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, moving methods outside of principal looks better.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

referencing istio here https://istio.io/latest/docs/reference/config/security/authorization-policy/#Operation
should we have a top level operation here ?
so we can have operation.methods and leave room for operation.paths in the future ?

@zirain zirain changed the title API for HTTP header and method based authz api: HTTP header and method based authz Feb 20, 2025
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
@zhaohuabing zhaohuabing requested a review from arkodg February 20, 2025 05:56
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=256
// +notImplementedHide
Headers []AuthorizationHeaderMatch `json:"headers,omitempty"`
Copy link
Copy Markdown
Member Author

@zhaohuabing zhaohuabing Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new AuthorizationHeaderMatch is introduced here, as the existing HeaderMatch is not suitable for authorization use case.

//
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=256
Values []string `json:"values"`
Copy link
Copy Markdown
Member Author

@zhaohuabing zhaohuabing Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only exact matches are supported for now. It should be good enough for authorization. If use cases for other matching types arise, we can add a MatchingType field later.

Name string `json:"name"`

// Value within the HTTP header. Due to the
// case-insensitivity of header names, "foo" and "Foo" are considered equivalent.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This existing comment seems to be in wrong place. Moving it to the header comment.

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
zhaohuabing and others added 2 commits February 22, 2025 21:20
Co-authored-by: Arko Dasgupta <arkodg@users.noreply.github.com>
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Copy link
Copy Markdown
Contributor

@arkodg arkodg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks !

@zhaohuabing zhaohuabing merged commit f1fbfb4 into envoyproxy:main Feb 23, 2025
27 of 28 checks passed
@zhaohuabing zhaohuabing deleted the authz-api branch February 23, 2025 13:27
@nathanwang-ops
Copy link
Copy Markdown

@zhaohuabing does it support xfcc header?

@zhaohuabing
Copy link
Copy Markdown
Member Author

@zhaohuabing does it support xfcc header?

@nathanwang-ops any arbitrary header in the HTTP request should be supported.

I think xfcc may deserve its own first-class API as a Principal in the SecurityPolicy's Authorization section.

Something like:

clientCert:
  Subject: foo.bar.com
  URI: http://foo.bar.com
  ...

@nathanwang-ops
Copy link
Copy Markdown

@zhaohuabing thank you for quick response, is there a feat for SecurityPolicy's Principal improvement?

@zhaohuabing
Copy link
Copy Markdown
Member Author

@zhaohuabing thank you for quick response, is there a feat for SecurityPolicy's Principal improvement?

#2250 did mentioned client cert auth, but it's marked as completed.

You can create one and linked it to #2250

@nathanwang-ops
Copy link
Copy Markdown

@zhaohuabing I just created the new feature request.
#5392

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants