mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-16 13:27:35 +03:00
add admin precedence to proxy role_map resolution to prevent downgrade
This commit is contained in:
parent
fe3677c7df
commit
82cb69526b
@ -166,6 +166,12 @@ In this example:
|
||||
- If no mapping matches, Frigate falls back to `default_role` if configured.
|
||||
- If `role_map` is not defined, Frigate assumes the role header directly contains `admin`, `viewer`, or a custom role name.
|
||||
|
||||
**Note on matching semantics:**
|
||||
|
||||
- Admin precedence: if the `admin` mapping matches , Frigate resolves the session to `admin` to avoid accidental downgrade
|
||||
when a user belongs to multiple groups (for example both admin and viewer
|
||||
groups).
|
||||
|
||||
#### Port Considerations
|
||||
|
||||
**Authenticated Port (8971)**
|
||||
|
||||
@ -439,10 +439,11 @@ def resolve_role(
|
||||
Determine the effective role for a request based on proxy headers and configuration.
|
||||
|
||||
Order of resolution:
|
||||
1. If a role header is defined in proxy_config.header_map.role:
|
||||
- If a role_map is configured, treat the header as group claims
|
||||
(split by proxy_config.separator) and map to roles.
|
||||
- If no role_map is configured, treat the header as role names directly.
|
||||
1. If a role header is defined in proxy_config.header_map.role:
|
||||
- If a role_map is configured, treat the header as group claims
|
||||
(split by proxy_config.separator) and map to roles.
|
||||
Admin matches short-circuit to admin.
|
||||
- If no role_map is configured, treat the header as role names directly.
|
||||
2. If no valid role is found, return proxy_config.default_role if it's valid in config_roles, else 'viewer'.
|
||||
|
||||
Args:
|
||||
@ -492,6 +493,12 @@ def resolve_role(
|
||||
}
|
||||
logger.debug("Matched roles from role_map: %s", matched_roles)
|
||||
|
||||
# If admin matches, prioritize it to avoid accidental downgrade when
|
||||
# users belong to both admin and lower-privilege groups.
|
||||
if "admin" in matched_roles and "admin" in config_roles:
|
||||
logger.debug("Resolved role (with role_map) to 'admin'.")
|
||||
return "admin"
|
||||
|
||||
if matched_roles:
|
||||
resolved = next(
|
||||
(r for r in config_roles if r in matched_roles), validated_default
|
||||
|
||||
@ -31,6 +31,21 @@ class TestProxyRoleResolution(unittest.TestCase):
|
||||
role = resolve_role(headers, self.proxy_config, self.config_roles)
|
||||
self.assertEqual(role, "admin")
|
||||
|
||||
def test_role_map_or_matching(self):
|
||||
config = self.proxy_config
|
||||
config.header_map.role_map = {
|
||||
"admin": ["group_admin", "group_privileged"],
|
||||
}
|
||||
|
||||
# OR semantics: a single matching group should map to the role
|
||||
headers = {"x-remote-role": "group_admin"}
|
||||
role = resolve_role(headers, config, self.config_roles)
|
||||
self.assertEqual(role, "admin")
|
||||
|
||||
headers = {"x-remote-role": "group_admin|group_privileged"}
|
||||
role = resolve_role(headers, config, self.config_roles)
|
||||
self.assertEqual(role, "admin")
|
||||
|
||||
def test_direct_role_header_with_separator(self):
|
||||
config = self.proxy_config
|
||||
config.header_map.role_map = None # disable role_map
|
||||
|
||||
Loading…
Reference in New Issue
Block a user