Skip to content

Commit e92da63

Browse files
fix(deploy): use JSON patch instead of merge patch for OIDC AuthPolicy
Merge patch (--type=merge) cannot reliably delete "when" arrays or replace "selector" with "expression" inside CRD objects. The live AuthPolicy showed both the base policy's when clause (restricting to sk-oai-*) AND the OIDC expression coexisting, causing X-MaaS-Username to be empty for OIDC tokens → 500 AUTH_FAILURE refId 003. Switch to JSON patch (--type=json) with op=replace on /spec/rules. This atomically replaces the entire rules block — no field merging, no stale when-clauses. Remove when:null and selector:null from the OIDC template since they are no longer needed. Signed-off-by: Wen Liang <liangwen12year@gmail.com>
1 parent 93d76db commit e92da63

2 files changed

Lines changed: 29 additions & 28 deletions

File tree

scripts/data/maas-api-authpolicy-external-oidc-patch.yaml

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
# Merge patch applied when EXTERNAL_OIDC=true (see configure_maas_api_authpolicy in deploy.sh).
1+
# OIDC rules applied when EXTERNAL_OIDC=true (see configure_maas_api_authpolicy in deploy.sh).
2+
# Applied via JSON patch (--type=json, op=replace on /spec/rules) to atomically replace
3+
# the entire rules block. Merge patch cannot reliably delete "when" arrays or replace
4+
# "selector" with "expression" inside CRD objects.
25
#
36
# Authentication order (lower priority number = earlier block; Authorino tries the next
47
# block when the previous identity method does not validate the token):
@@ -72,45 +75,29 @@ spec:
7275
response:
7376
success:
7477
headers:
75-
# Override the base X-MaaS-Username / X-MaaS-Group headers so they
76-
# handle API keys, OIDC JWT, and OpenShift TokenReview.
77-
#
78-
# API keys (Bearer sk-oai-*): identity comes from apiKeyValidation metadata — the
79-
# base policy used plain selectors here. OIDC-only expressions omit that path and
80-
# yield empty username → maas-api HTTP 500 AUTH_FAILURE refId 001 on /v1/models.
81-
# Order: apiKeyValidation → OIDC claims → OpenShift TokenReview.
82-
# No "when" clause — these headers must apply to ALL token types (API keys,
83-
# OIDC JWT, OpenShift TokenReview). The three-way expression handles each case.
84-
# The base policy restricts these to sk-oai-* only; merge patch must explicitly
85-
# null the "when" to clear the base's restriction.
78+
# Three-way CEL expressions handle API keys, OIDC JWT, and OpenShift
79+
# TokenReview without any "when" clause. JSON patch replaces the entire
80+
# rules block, so base policy fields (when, selector) are not inherited.
8681
X-MaaS-Username:
87-
when: null
8882
plain:
89-
selector: null
9083
expression: >-
9184
(has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ?
9285
auth.metadata.apiKeyValidation.username :
9386
(has(auth.identity.preferred_username) ?
9487
auth.identity.preferred_username :
9588
(has(auth.identity.sub) ? auth.identity.sub : auth.identity.user.username))
96-
# Never call .join on a missing path — that stringifies nil as "<nil>"
97-
# and breaks maas-api JSON parsing.
9889
X-MaaS-Group:
99-
when: null
10090
plain:
101-
selector: null
10291
expression: >-
10392
(has(auth.metadata) && has(auth.metadata.apiKeyValidation)) ?
10493
(size(auth.metadata.apiKeyValidation.groups) > 0 ?
10594
'["' + auth.metadata.apiKeyValidation.groups.join('","') + '"]' :
10695
'["system:authenticated"]') :
10796
(has(auth.identity.groups) && size(auth.identity.groups) > 0 ?
10897
'["system:authenticated","' + auth.identity.groups.join('","') + '"]' :
109-
(has(auth.identity.user.groups) && size(auth.identity.user.groups) > 0 ?
98+
(has(auth.identity.user) && has(auth.identity.user.groups) && size(auth.identity.user.groups) > 0 ?
11099
'["system:authenticated","' + auth.identity.user.groups.join('","') + '"]' :
111100
'["system:authenticated"]'))
112-
# Subscription: from API key validation (must be preserved from base policy).
113-
# /v1/models reads this header to filter by subscription.
114101
X-MaaS-Subscription:
115102
when:
116103
- selector: request.headers.authorization

scripts/deploy.sh

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,17 +1492,31 @@ patch_authpolicy_from_template() {
14921492
local oidc_issuer_url="${4:-}"
14931493
local oidc_client_id="${5:-}"
14941494

1495-
local rendered_patch
1496-
rendered_patch="$(mktemp)"
1497-
1495+
# Render placeholders in the YAML template.
1496+
local rendered_yaml
1497+
rendered_yaml="$(mktemp)"
14981498
sed \
14991499
-e "s|__MAAS_NAMESPACE__|${maas_namespace}|g" \
15001500
-e "s|__OIDC_ISSUER_URL__|${oidc_issuer_url}|g" \
15011501
-e "s|__OIDC_CLIENT_ID__|${oidc_client_id}|g" \
1502-
"$template_file" > "$rendered_patch"
1503-
1504-
kubectl patch authpolicy "$authpolicy_name" -n "$NAMESPACE" --type=merge --patch-file "$rendered_patch"
1505-
rm -f "$rendered_patch"
1502+
"$template_file" > "$rendered_yaml"
1503+
1504+
# Use JSON patch (--type=json) with op=replace on /spec/rules to atomically
1505+
# replace the entire rules block. Merge patch (--type=merge) cannot reliably
1506+
# delete fields like "when" arrays or replace "selector" with "expression"
1507+
# inside CRD objects, causing stale when-clauses to persist and break OIDC.
1508+
local rules_json
1509+
rules_json=$(python3 -c "
1510+
import sys, json, yaml
1511+
with open('$rendered_yaml') as f:
1512+
doc = yaml.safe_load(f)
1513+
rules = doc.get('spec', {}).get('rules', {})
1514+
patch = [{'op': 'replace', 'path': '/spec/rules', 'value': rules}]
1515+
json.dump(patch, sys.stdout)
1516+
")
1517+
rm -f "$rendered_yaml"
1518+
1519+
kubectl patch authpolicy "$authpolicy_name" -n "$NAMESPACE" --type=json -p "$rules_json"
15061520
}
15071521

15081522
# configure_maas_api_authpolicy

0 commit comments

Comments
 (0)