1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-03-22 13:19:13 +00:00

keycloak_authentication_v2: covers idp flow overrides in safe swap (fix 11582) (#11601)

* 11582 keycloak_authentication_v2 covers idp flow overrides in safe swap

* 11583 update documentation and comments

(cherry picked from commit e7a253b4c9)
This commit is contained in:
thomasbargetz 2026-03-18 06:49:24 +01:00 committed by patchback[bot]
parent a8bd4c750b
commit fe43b9f5f2
5 changed files with 167 additions and 61 deletions

View file

@ -16,8 +16,8 @@ description:
- Rather than modifying an existing flow in place, the module re-creates the flow using the B(Safe Swap) mechanism described below.
- B(Safe Swap mechanism) - When an authentication flow needs to be updated, the module never modifies the existing flow in place.
Instead it follows a multi-step swap procedure to ensure the flow is never left in an intermediate or unsafe state during the update.
This is especially important when the flow is actively bound to a realm binding or a client override,
because a partially-updated flow could inadvertently allow unauthorised access.
This is especially important when the flow is actively bound to a realm binding, a client override, or as an identity-provider
login-flow or post-flow, because a partially-updated flow could inadvertently allow unauthorised access.
- The B(Safe Swap mechanism) is as follows. 1. A new flow is created under a temporary name (the original alias plus a configurable suffix,
for example C(myflow_tmp_for_swap)).
2. All executions and their configurations are added to the new temporary flow. 3. If the existing flow is currently bound to a realm or a client,
@ -639,8 +639,8 @@ def existing_auth_to_diff_repr(kc: KeycloakAPI, realm: str, existing_auth: dict)
def is_auth_flow_in_use(kc: KeycloakAPI, realm: str, existing_auth: dict) -> bool:
"""Determine whether the given flow is currently bound to a realm binding or a client
authentication flow override.
"""Determine whether the given flow is currently bound to a realm binding, a client
authentication flow override or as an identity-provider login-flow or post-flow.
:param kc: a KeycloakAPI instance.
:param realm: the realm to inspect.
@ -673,6 +673,12 @@ def is_auth_flow_in_use(kc: KeycloakAPI, realm: str, existing_auth: dict) -> boo
if overrides.get("direct_grant") == flow_id:
return True
for identity_provider in kc.get_identity_providers(realm):
first_broker_login_flow_alias = identity_provider.get("firstBrokerLoginFlowAlias")
post_broker_login_flow_alias = identity_provider.get("postBrokerLoginFlowAlias")
if first_broker_login_flow_alias == flow_alias or post_broker_login_flow_alias == flow_alias:
return True
return False
@ -684,8 +690,8 @@ def rebind_auth_flow_bindings(
to_id: str,
to_alias: str,
) -> None:
"""Re-point all realm bindings and client overrides that reference the source flow to the
target flow.
"""Re-point all realm bindings, client flow overrides and identity-provider login-flows or post-flows
that reference the source flow to the target flow.
This is the critical step in the Safe Swap procedure that transfers live bindings from the
old flow to the newly-created temporary flow without any gap in coverage.
@ -733,6 +739,22 @@ def rebind_auth_flow_bindings(
if client_changed:
kc.update_client(id=client["id"], clientrep=client, realm=realm)
for identity_provider in kc.get_identity_providers(realm):
first_broker_login_flow_alias = identity_provider.get("firstBrokerLoginFlowAlias")
post_broker_login_flow_alias = identity_provider.get("postBrokerLoginFlowAlias")
identity_provider_changed = False
if first_broker_login_flow_alias == from_alias:
identity_provider["firstBrokerLoginFlowAlias"] = to_alias
identity_provider_changed = True
if post_broker_login_flow_alias == from_alias:
identity_provider["postBrokerLoginFlowAlias"] = to_alias
identity_provider_changed = True
if identity_provider_changed:
kc.update_identity_provider(idprep=identity_provider, realm=realm)
def delete_tmp_swap_flow_if_exists(
kc: KeycloakAPI,