fix: accept pipe-separated trusted-groups header values
Authentik's proxy provider on this deployment joins multiple group names with "|" instead of "," (e.g. "admins|developpeur"). The comma-only split in _trusted_groups_header_value() treated that whole string as a single unmatched group name, silently dropping the session to the unbound "default" profile even for identities that are legitimate members of a mapped group. Single-group identities were never affected since there was no separator to parse. Accept comma, pipe, and newline as equivalent separators so the parser works regardless of which the outpost happens to send.
This commit is contained in:
1 parent
e168b67e42
commit
bb5347e1cd
2 files changed
+38
-1
No files matched your search
+10
-1
@@ -722,7 +722,16 @@ def _trusted_groups_header_value(handler) -> list[str]:
|
||||
if not raw:
|
||||
return []
|
||||
values = []
|
||||
for part in str(raw).replace('\n', ',').split(','):
|
||||
# Authentik's outpost typically joins multiple group names with a comma,
|
||||
# but this deployment's proxy provider/property mapping emits a
|
||||
# pipe-separated list instead (e.g. "admins|developpeur"). A bare comma
|
||||
# split silently treats a multi-group pipe-joined value as one unmatched
|
||||
# group name, dropping the session to the unbound "default" profile even
|
||||
# though the identity is a legitimate member of a mapped group. Accept
|
||||
# comma, pipe, and newline as equivalent separators so either format
|
||||
# works regardless of which the outpost happens to send.
|
||||
normalized = str(raw).replace('\n', ',').replace('|', ',')
|
||||
for part in normalized.split(','):
|
||||
part = part.strip()
|
||||
if part:
|
||||
values.append(part)
|
||||
|
||||
@@ -212,6 +212,34 @@ def test_group_map_prefers_mapping_order_over_header_order(monkeypatch):
|
||||
assert auth.ensure_trusted_auth_session(second)["bound_profile"] == "ops"
|
||||
|
||||
|
||||
def test_group_map_accepts_pipe_separated_header_value(monkeypatch):
|
||||
# Some Authentik proxy provider / property mapping configs join multiple
|
||||
# group names with "|" instead of ",". Regression case for the identity
|
||||
# falling back to the unbound "default" profile despite being a member
|
||||
# of a mapped group: a lone-membership identity works fine (no
|
||||
# separator to parse), but a second group membership starts producing a
|
||||
# pipe-joined header value that a comma-only split can't see through.
|
||||
#
|
||||
# NOTE: this only covers the concrete-mapped-group case. The
|
||||
# wildcard-mapped-group case (a "*" mapping value dominating a concrete
|
||||
# one) is intentionally not exercised here — that precedence rule isn't
|
||||
# implemented on this branch yet; it ships separately in #6798. See the
|
||||
# PR description for the full scope note.
|
||||
_trusted_env(
|
||||
monkeypatch,
|
||||
groups_header="Remote-Groups",
|
||||
group_map={"hermes_devops": "devops"},
|
||||
)
|
||||
handler = _Handler(
|
||||
headers={"Remote-User": "alice", "Remote-Groups": "hermes_devops|other_group"}
|
||||
)
|
||||
|
||||
info = auth.ensure_trusted_auth_session(handler)
|
||||
|
||||
assert info["bound_profile"] == "devops"
|
||||
assert auth.trusted_session_allows_active_profile(info) is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"group_map",
|
||||
[
|
||||
|
||||
Reference in new issue
Block a user