From 9cc1a16ba16c349de734d3db8283894c19d2935d Mon Sep 17 00:00:00 2001 From: Andrejs Mivreniks Date: Sat, 1 Jun 2024 12:42:52 +0300 Subject: [PATCH] Add priority field support in authentication flow executions and subflows Fixes #296 Signed-off-by: Andrejs Mivreniks --- docs/resources/authentication_execution.md | 6 +++- docs/resources/authentication_subflow.md | 2 ++ keycloak/authentication_execution.go | 9 +++++- keycloak/authentication_subflow.go | 30 ++----------------- ...ource_keycloak_authentication_execution.go | 7 +++++ ...esource_keycloak_authentication_subflow.go | 6 ++++ 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/resources/authentication_execution.md b/docs/resources/authentication_execution.md index 15f5b1bd3..637edb494 100644 --- a/docs/resources/authentication_execution.md +++ b/docs/resources/authentication_execution.md @@ -9,7 +9,7 @@ Allows for creating and managing an authentication execution within Keycloak. An authentication execution is an action that the user or service may or may not take when authenticating through an authentication flow. -~> Due to limitations in the Keycloak API, the ordering of authentication executions within a flow must be specified using `depends_on`. Authentication executions that are created first will appear first within the flow. +~> Due to limitations in the Keycloak API, the ordering of authentication executions within a flow must be specified using `depends_on` in versions prior to Keycloak 25. Authentication executions that are created first will appear first within the flow. ## Example Usage @@ -30,6 +30,7 @@ resource "keycloak_authentication_execution" "execution_one" { parent_flow_alias = "${keycloak_authentication_flow.flow.alias}" authenticator = "auth-cookie" requirement = "ALTERNATIVE" + priority = 10 # Starting from Keycloak 25 } # second execution @@ -38,7 +39,9 @@ resource "keycloak_authentication_execution" "execution_two" { parent_flow_alias = "${keycloak_authentication_flow.flow.alias}" authenticator = "identity-provider-redirector" requirement = "ALTERNATIVE" + priority = 20 # Starting from Keycloak 25 + # Workaround for older Keycloak versions (Keycloak 24 and older) depends_on = [ keycloak_authentication_execution.execution_one ] @@ -51,6 +54,7 @@ resource "keycloak_authentication_execution" "execution_two" { - `parent_flow_alias` - (Required) The alias of the flow this execution is attached to. - `authenticator` - (Required) The name of the authenticator. This can be found by experimenting with the GUI and looking at HTTP requests within the network tab of your browser's development tools. - `requirement`- (Optional) The requirement setting, which can be one of `REQUIRED`, `ALTERNATIVE`, `OPTIONAL`, `CONDITIONAL`, or `DISABLED`. Defaults to `DISABLED`. +- `priority`- (Optional) The authenticator priority, the lower the value the higher it will be placed in the parent flow. This option is supported only by Keycloak 25 and onwards. ## Import diff --git a/docs/resources/authentication_subflow.md b/docs/resources/authentication_subflow.md index e22d189e8..29ebb91e6 100644 --- a/docs/resources/authentication_subflow.md +++ b/docs/resources/authentication_subflow.md @@ -28,6 +28,7 @@ resource "keycloak_authentication_subflow" "subflow" { parent_flow_alias = keycloak_authentication_flow.flow.alias provider_id = "basic-flow" requirement = "ALTERNATIVE" + priority = 10 # Starting from Keycloak 25 } ``` @@ -43,6 +44,7 @@ and `client-flow`. Defaults to `basic-flow`. authenticators. In general this will remain empty. - `requirement`- (Optional) The requirement setting, which can be one of `REQUIRED`, `ALTERNATIVE`, `OPTIONAL`, `CONDITIONAL`, or `DISABLED`. Defaults to `DISABLED`. +- `priority`- (Optional) The subflow priority, the lower the value the higher it will be placed in the parent flow. This option is supported only by Keycloak 25 and onwards. ## Import diff --git a/keycloak/authentication_execution.go b/keycloak/authentication_execution.go index 971448eea..083f4d873 100644 --- a/keycloak/authentication_execution.go +++ b/keycloak/authentication_execution.go @@ -11,6 +11,7 @@ import ( // POST /realms/${realmId}/authentication/flows/${flowAlias}/executions/execution type authenticationExecutionCreate struct { Provider string `json:"provider"` //authenticator of the execution + Priority int `json:"priority"` } type authenticationExecutionRequirementUpdate struct { @@ -18,6 +19,7 @@ type authenticationExecutionRequirementUpdate struct { ParentFlowAlias string `json:"-"` Id string `json:"id"` Requirement string `json:"requirement"` + Priority int `json:"priority"` } // this type is returned by GET /realms/${realmId}/authentication/flows/${flowAlias}/executions @@ -47,6 +49,7 @@ type AuthenticationExecutionInfo struct { Index int `json:"index"` Level int `json:"level"` ProviderId string `json:"providerId"` + Priority int `json:"priority"` Requirement string `json:"requirement"` } @@ -119,7 +122,10 @@ func (keycloakClient *KeycloakClient) GetAuthenticationExecutionInfoFromProvider } func (keycloakClient *KeycloakClient) NewAuthenticationExecution(ctx context.Context, execution *AuthenticationExecution) error { - _, location, err := keycloakClient.post(ctx, fmt.Sprintf("/realms/%s/authentication/flows/%s/executions/execution", execution.RealmId, execution.ParentFlowAlias), &authenticationExecutionCreate{Provider: execution.Authenticator}) + _, location, err := keycloakClient.post(ctx, fmt.Sprintf("/realms/%s/authentication/flows/%s/executions/execution", execution.RealmId, execution.ParentFlowAlias), &authenticationExecutionCreate{ + Provider: execution.Authenticator, + Priority: execution.Priority, + }) if err != nil { return err } @@ -154,6 +160,7 @@ func (keycloakClient *KeycloakClient) UpdateAuthenticationExecution(ctx context. ParentFlowAlias: execution.ParentFlowAlias, Id: execution.Id, Requirement: execution.Requirement, + Priority: execution.Priority, } return keycloakClient.UpdateAuthenticationExecutionRequirement(ctx, authenticationExecutionUpdateRequirement) } diff --git a/keycloak/authentication_subflow.go b/keycloak/authentication_subflow.go index 593facb94..0407b4e05 100644 --- a/keycloak/authentication_subflow.go +++ b/keycloak/authentication_subflow.go @@ -71,6 +71,7 @@ func (keycloakClient *KeycloakClient) GetAuthenticationSubFlow(ctx context.Conte } authenticationSubFlow.Authenticator = subFlowExecution.Authenticator authenticationSubFlow.Requirement = subFlowExecution.Requirement + authenticationSubFlow.Priority = subFlowExecution.Priority return &authenticationSubFlow, nil } @@ -110,6 +111,7 @@ func (keycloakClient *KeycloakClient) UpdateAuthenticationSubFlow(ctx context.Co ParentFlowAlias: authenticationSubFlow.ParentFlowAlias, Id: executionId, Requirement: authenticationSubFlow.Requirement, + Priority: authenticationSubFlow.Priority, } return keycloakClient.UpdateAuthenticationExecutionRequirement(ctx, authenticationExecutionUpdateRequirement) @@ -128,31 +130,3 @@ func (keycloakClient *KeycloakClient) DeleteAuthenticationSubFlow(ctx context.Co return keycloakClient.DeleteAuthenticationExecution(ctx, authenticationSubFlow.RealmId, executionId) } - -func (keycloakClient *KeycloakClient) RaiseAuthenticationSubFlowPriority(ctx context.Context, realmId, parentFlowAlias, id string) error { - authenticationSubFlow := AuthenticationSubFlow{ - Id: id, - ParentFlowAlias: parentFlowAlias, - RealmId: realmId, - } - executionId, err := keycloakClient.getExecutionId(ctx, &authenticationSubFlow) - if err != nil { - return err - } - - return keycloakClient.RaiseAuthenticationExecutionPriority(ctx, authenticationSubFlow.RealmId, executionId) -} - -func (keycloakClient *KeycloakClient) LowerAuthenticationSubFlowPriority(ctx context.Context, realmId, parentFlowAlias, id string) error { - authenticationSubFlow := AuthenticationSubFlow{ - Id: id, - ParentFlowAlias: parentFlowAlias, - RealmId: realmId, - } - executionId, err := keycloakClient.getExecutionId(ctx, &authenticationSubFlow) - if err != nil { - return err - } - - return keycloakClient.LowerAuthenticationExecutionPriority(ctx, authenticationSubFlow.RealmId, executionId) -} diff --git a/provider/resource_keycloak_authentication_execution.go b/provider/resource_keycloak_authentication_execution.go index 59a3d21ba..c2de80271 100644 --- a/provider/resource_keycloak_authentication_execution.go +++ b/provider/resource_keycloak_authentication_execution.go @@ -43,6 +43,10 @@ func resourceKeycloakAuthenticationExecution() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"REQUIRED", "ALTERNATIVE", "OPTIONAL", "CONDITIONAL", "DISABLED"}, false), //OPTIONAL is removed from 8.0.0 onwards Default: "DISABLED", }, + "priority": { + Type: schema.TypeInt, + Optional: true, + }, }, } } @@ -54,6 +58,7 @@ func mapFromDataToAuthenticationExecution(data *schema.ResourceData) *keycloak.A ParentFlowAlias: data.Get("parent_flow_alias").(string), Authenticator: data.Get("authenticator").(string), Requirement: data.Get("requirement").(string), + Priority: data.Get("priority").(int), } return authenticationExecution @@ -66,6 +71,7 @@ func mapFromAuthenticationExecutionToData(data *schema.ResourceData, authenticat data.Set("parent_flow_alias", authenticationExecution.ParentFlowAlias) data.Set("authenticator", authenticationExecution.Authenticator) data.Set("requirement", authenticationExecution.Requirement) + data.Set("priority", authenticationExecution.Priority) } func mapFromAuthenticationExecutionInfoToData(data *schema.ResourceData, authenticationExecutionInfo *keycloak.AuthenticationExecutionInfo) { @@ -73,6 +79,7 @@ func mapFromAuthenticationExecutionInfoToData(data *schema.ResourceData, authent data.Set("realm_id", authenticationExecutionInfo.RealmId) data.Set("parent_flow_alias", authenticationExecutionInfo.ParentFlowAlias) + data.Set("priority", authenticationExecutionInfo.Priority) } func resourceKeycloakAuthenticationExecutionCreate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { diff --git a/provider/resource_keycloak_authentication_subflow.go b/provider/resource_keycloak_authentication_subflow.go index d9e5728e6..ccb9e492b 100644 --- a/provider/resource_keycloak_authentication_subflow.go +++ b/provider/resource_keycloak_authentication_subflow.go @@ -59,6 +59,10 @@ func resourceKeycloakAuthenticationSubFlow() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"REQUIRED", "ALTERNATIVE", "OPTIONAL", "CONDITIONAL", "DISABLED"}, false), //OPTIONAL is removed from 8.0.0 onwards Default: "DISABLED", }, + "priority": { + Type: schema.TypeInt, + Optional: true, + }, }, } } @@ -73,6 +77,7 @@ func mapFromDataToAuthenticationSubFlow(data *schema.ResourceData) *keycloak.Aut Description: data.Get("description").(string), Authenticator: data.Get("authenticator").(string), Requirement: data.Get("requirement").(string), + Priority: data.Get("priority").(int), } return authenticationSubFlow @@ -87,6 +92,7 @@ func mapFromAuthenticationSubFlowToData(data *schema.ResourceData, authenticatio data.Set("description", authenticationSubFlow.Description) data.Set("authenticator", authenticationSubFlow.Authenticator) data.Set("requirement", authenticationSubFlow.Requirement) + data.Set("priority", authenticationSubFlow.Priority) } func resourceKeycloakAuthenticationSubFlowCreate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {