Skip to content

Commit

Permalink
feat: OR operator for the pattern-matching (conditions and pattern-ma…
Browse files Browse the repository at this point in the history
…tching authorization)

Adds support for logical disjunction (aka "OR" operator) in 'when' conditions and pattern-matching authorization rules.

A new field `any: Array<expression>` was introduced to the AuthConfig API to express logical disjunction, along with `all: Array<expression>` to enforce the default AND operation, where `expression` can be any of the following:
- a pattern composed of `selector`, `operator` and `value`;
- a reference to a named pattern (`patternRef: String`);
- a nested `any` field;
- a nested `all` field.

For backward compatibility, the AND operator is assumed for all lists of patterns not grouped under an explicit `any` field declaration. I.e., it is equivalent to grouping the patterns under a single `all` field declaration.

Example 1) To allow anonymous access (no authentication required) for all request to path `/test/*` OR method `GET` (ocasionally both):

```yaml
spec:
  authentication:
    anonymous-request:
      when:
      - any:
        - selector: context.request.http.path
          operator: matches
          value: ^/test/.*
        - selector: context.request.http.method
          operator: eq
          method: GET
      anonymous: {}
```

In a more complex condition, with nested logical operators, to express `host == 'foo.apis.io' AND ((path =~ '/test*' AND (method == 'POST' OR method == 'PUT')) OR method == 'GET')`:

```yaml
spec:
  authentication:
    anonymous-request:
      when:
      - selector: context.request.http.host
        operator: eq
        value: foo.apis.io
      - any:
        - all:
          - selector: context.request.http.path
            operator: matches
            value: ^/test/.*
          - any:
            - selector: context.request.http.method
              operator: eq
              value: POST
            - selector: context.request.http.method
              operator: eq
              value: PUT
        - selector: context.request.http.method
          operator: eq
          value: GET
      anonymous: {}
```
  • Loading branch information
guicassolato committed Sep 20, 2023
1 parent 5fc204a commit 2706687
Show file tree
Hide file tree
Showing 24 changed files with 1,673 additions and 277 deletions.
10 changes: 10 additions & 0 deletions api/v1beta1/auth_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,16 @@ type AuthConfigSpec struct {
type JSONPattern struct {
JSONPatternRef `json:",omitempty"`
JSONPatternExpression `json:",omitempty"`

// A list of pattern expressions to be evaluated as a logical AND.
All []UnstructuredJSONPattern `json:"all,omitempty"`
// A list of pattern expressions to be evaluated as a logical OR.
Any []UnstructuredJSONPattern `json:"any,omitempty"`
}

type UnstructuredJSONPattern struct {
// +kubebuilder:pruning:PreserveUnknownFields
JSONPattern `json:",omitempty"`
}

type JSONPatternRef struct {
Expand Down
58 changes: 51 additions & 7 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 28 additions & 2 deletions api/v1beta2/auth_config_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,21 +216,47 @@ func convertPatternExpressionFrom(src v1beta1.JSONPatternExpression) PatternExpr
}

func convertPatternExpressionOrRefTo(src PatternExpressionOrRef) v1beta1.JSONPattern {
return v1beta1.JSONPattern{
pattern := v1beta1.JSONPattern{
JSONPatternExpression: convertPatternExpressionTo(src.PatternExpression),
JSONPatternRef: v1beta1.JSONPatternRef{
JSONPatternName: src.PatternRef.Name,
},
}
if len(src.All) > 0 {
pattern.All = make([]v1beta1.UnstructuredJSONPattern, len(src.All))
for i, p := range src.All {
pattern.All[i] = v1beta1.UnstructuredJSONPattern{JSONPattern: convertPatternExpressionOrRefTo(p.PatternExpressionOrRef)}
}
}
if len(src.Any) > 0 {
pattern.Any = make([]v1beta1.UnstructuredJSONPattern, len(src.Any))
for i, p := range src.Any {
pattern.Any[i] = v1beta1.UnstructuredJSONPattern{JSONPattern: convertPatternExpressionOrRefTo(p.PatternExpressionOrRef)}
}
}
return pattern
}

func convertPatternExpressionOrRefFrom(src v1beta1.JSONPattern) PatternExpressionOrRef {
return PatternExpressionOrRef{
pattern := PatternExpressionOrRef{
PatternExpression: convertPatternExpressionFrom(src.JSONPatternExpression),
PatternRef: PatternRef{
Name: src.JSONPatternRef.JSONPatternName,
},
}
if len(src.All) > 0 {
pattern.All = make([]UnstructuredPatternExpressionOrRef, len(src.All))
for i, p := range src.All {
pattern.All[i] = UnstructuredPatternExpressionOrRef{convertPatternExpressionOrRefFrom(p.JSONPattern)}
}
}
if len(src.Any) > 0 {
pattern.Any = make([]UnstructuredPatternExpressionOrRef, len(src.Any))
for i, p := range src.Any {
pattern.Any[i] = UnstructuredPatternExpressionOrRef{convertPatternExpressionOrRefFrom(p.JSONPattern)}
}
}
return pattern
}

func convertEvaluatorCachingTo(src *EvaluatorCaching) *v1beta1.EvaluatorCaching {
Expand Down
10 changes: 10 additions & 0 deletions api/v1beta2/auth_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ type PatternExpressionOperator string
type PatternExpressionOrRef struct {
PatternExpression `json:",omitempty"`
PatternRef `json:",omitempty"`

// A list of pattern expressions to be evaluated as a logical AND.
All []UnstructuredPatternExpressionOrRef `json:"all,omitempty"`
// A list of pattern expressions to be evaluated as a logical OR.
Any []UnstructuredPatternExpressionOrRef `json:"any,omitempty"`
}

type UnstructuredPatternExpressionOrRef struct {
// +kubebuilder:pruning:PreserveUnknownFields
PatternExpressionOrRef `json:",omitempty"`
}

type PatternRef struct {
Expand Down
42 changes: 39 additions & 3 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 2706687

Please sign in to comment.