api: HTTP header and method based authz#5310
Conversation
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Codecov ReportAll modified and coverable lines are covered by tests ✅
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. |
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
api/v1alpha1/authorization_types.go
Outdated
| // +optional | ||
| JWT *JWTPrincipal `json:"jwt,omitempty"` | ||
|
|
||
| // Headers authorize the request based on the headers in the request. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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: salesFor 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: barOne 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.
There was a problem hiding this 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
is too lengthy, the common case is there will be hundreds of such entries, which requires 5x more lines
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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]
api/v1alpha1/authorization_types.go
Outdated
| // +optional | ||
| // +kubebuilder:validation:MinItems=1 | ||
| // +notImplementedHide | ||
| Methods []gwapiv1.HTTPMethod `json:"methods,omitempty"` |
There was a problem hiding this comment.
should methods live in the top level outside principal because its falls under actions / operation performed by the principal
There was a problem hiding this comment.
Yeah, moving methods outside of principal looks better.
There was a problem hiding this comment.
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 ?
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
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"` |
There was a problem hiding this comment.
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"` |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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>
Co-authored-by: Arko Dasgupta <arkodg@users.noreply.github.com> Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
|
@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 Something like: |
|
@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 |
|
@zhaohuabing I just created the new feature request. |
API for #4660 and #4661