diff --git a/docs/resources/required_action.md b/docs/resources/required_action.md index 9ca6901a..28b0eaa9 100644 --- a/docs/resources/required_action.md +++ b/docs/resources/required_action.md @@ -19,9 +19,12 @@ resource "keycloak_realm" "realm" { resource "keycloak_required_action" "required_action" { realm_id = keycloak_realm.realm.realm - alias = "webauthn-register" + alias = "UPDATE_PASSWORD" enabled = true - name = "Webauthn Register" + name = "Update Password" + config = { + max_auth_age = "600" + } } ``` @@ -33,6 +36,7 @@ resource "keycloak_required_action" "required_action" { - `enabled` - (Optional) When `false`, the required action is not enabled for new users. Defaults to `false`. - `default_action` - (Optional) When `true`, the required action is set as the default action for new users. Defaults to `false`. - `priority`- (Optional) The priority of the required action. +- `config`- (Optional) The configuration. Keys are specific to each configurable required action and not checked when applying. ## Import diff --git a/example/main.tf b/example/main.tf index 90172fd1..ae2d1acc 100644 --- a/example/main.tf +++ b/example/main.tf @@ -109,6 +109,18 @@ resource "keycloak_required_action" "custom-terms-and-conditions" { name = "Custom Terms and Conditions" } +resource "keycloak_required_action" "update-password" { + realm_id = keycloak_realm.test.realm + alias = "UPDATE_PASSWORD" + default_action = true + enabled = true + name = "Update Password" + + config { + max_auth_age = "600" + } +} + resource "keycloak_required_action" "custom-configured_totp" { realm_id = keycloak_realm.test.realm alias = "CONFIGURE_TOTP" @@ -1020,7 +1032,7 @@ resource "keycloak_authentication_execution" "browser-copy-cookie" { parent_flow_alias = keycloak_authentication_flow.browser-copy-flow.alias authenticator = "auth-cookie" requirement = "ALTERNATIVE" - priority = 20 + priority = 20 } resource "keycloak_authentication_execution" "browser-copy-kerberos" { @@ -1028,7 +1040,7 @@ resource "keycloak_authentication_execution" "browser-copy-kerberos" { parent_flow_alias = keycloak_authentication_flow.browser-copy-flow.alias authenticator = "auth-spnego" requirement = "DISABLED" - priority = 10 + priority = 10 } resource "keycloak_authentication_execution" "browser-copy-idp-redirect" { @@ -1036,7 +1048,7 @@ resource "keycloak_authentication_execution" "browser-copy-idp-redirect" { parent_flow_alias = keycloak_authentication_flow.browser-copy-flow.alias authenticator = "identity-provider-redirector" requirement = "ALTERNATIVE" - priority = 30 + priority = 30 } resource "keycloak_authentication_subflow" "browser-copy-flow-forms" { @@ -1044,7 +1056,7 @@ resource "keycloak_authentication_subflow" "browser-copy-flow-forms" { parent_flow_alias = keycloak_authentication_flow.browser-copy-flow.alias alias = "browser-copy-flow-forms" requirement = "ALTERNATIVE" - priority = 40 + priority = 40 } resource "keycloak_authentication_execution" "browser-copy-auth-username-password-form" { @@ -1052,7 +1064,7 @@ resource "keycloak_authentication_execution" "browser-copy-auth-username-passwor parent_flow_alias = keycloak_authentication_subflow.browser-copy-flow-forms.alias authenticator = "auth-username-password-form" requirement = "REQUIRED" - priority = 50 + priority = 50 } resource "keycloak_authentication_execution" "browser-copy-otp" { @@ -1060,7 +1072,7 @@ resource "keycloak_authentication_execution" "browser-copy-otp" { parent_flow_alias = keycloak_authentication_subflow.browser-copy-flow-forms.alias authenticator = "auth-otp-form" requirement = "REQUIRED" - priority = 60 + priority = 60 } resource "keycloak_authentication_execution_config" "config" { diff --git a/keycloak/required_action.go b/keycloak/required_action.go index d46c3db9..5893f556 100644 --- a/keycloak/required_action.go +++ b/keycloak/required_action.go @@ -6,31 +6,30 @@ import ( ) type RequiredAction struct { - Id string `json:"-"` - RealmId string `json:"-"` - Alias string `json:"alias"` - Name string `json:"name"` - ProviderId string `json:"providerId"` - Enabled bool `json:"enabled"` - DefaultAction bool `json:"defaultAction"` - Priority int `json:"priority"` - Config map[string][]string `json:"config"` + Id string `json:"-"` + RealmId string `json:"-"` + Alias string `json:"alias"` + Name string `json:"name"` + ProviderId string `json:"providerId"` + Enabled bool `json:"enabled"` + DefaultAction bool `json:"defaultAction"` + Priority int `json:"priority"` + Config map[string]string `json:"config"` } func (requiredActions *RequiredAction) getConfig(val string) string { if len(requiredActions.Config[val]) == 0 { return "" } - return requiredActions.Config[val][0] + return requiredActions.Config[val] } func (requiredActions *RequiredAction) getConfigOk(val string) (string, bool) { if v, ok := requiredActions.Config[val]; ok { - return v[0], true + return v, true } return "", false } - func (keycloakClient *KeycloakClient) GetRequiredActions(ctx context.Context, realmId string) ([]*RequiredAction, error) { var requiredActions []*RequiredAction diff --git a/provider/resource_keycloak_required_action.go b/provider/resource_keycloak_required_action.go index f9ccce2c..c9e04665 100644 --- a/provider/resource_keycloak_required_action.go +++ b/provider/resource_keycloak_required_action.go @@ -47,11 +47,21 @@ func resourceKeycloakRequiredAction() *schema.Resource { Optional: true, Computed: true, }, + "config": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, }, } } func getRequiredActionFromData(data *schema.ResourceData) (*keycloak.RequiredAction, error) { + config := make(map[string]string) + for key, value := range data.Get("config").(map[string]interface{}) { + config[key] = value.(string) + } + action := &keycloak.RequiredAction{ Id: fmt.Sprintf("%s/%s", data.Get("realm_id").(string), data.Get("alias").(string)), RealmId: data.Get("realm_id").(string), @@ -60,7 +70,7 @@ func getRequiredActionFromData(data *schema.ResourceData) (*keycloak.RequiredAct Enabled: data.Get("enabled").(bool), DefaultAction: data.Get("default_action").(bool), Priority: data.Get("priority").(int), - Config: make(map[string][]string), + Config: config, } return action, nil @@ -74,6 +84,7 @@ func setRequiredActionData(data *schema.ResourceData, action *keycloak.RequiredA data.Set("enabled", action.Enabled) data.Set("default_action", action.DefaultAction) data.Set("priority", action.Priority) + data.Set("config", action.Config) } func resourceKeycloakRequiredActionsCreate(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { diff --git a/provider/resource_keycloak_required_action_test.go b/provider/resource_keycloak_required_action_test.go index 989d80ec..8380e781 100644 --- a/provider/resource_keycloak_required_action_test.go +++ b/provider/resource_keycloak_required_action_test.go @@ -26,6 +26,28 @@ func TestAccKeycloakRequiredAction_basic(t *testing.T) { }) } +func TestAccKeycloakRequiredAction_withConfig(t *testing.T) { + realmName := acctest.RandomWithPrefix("tf-acc") + requiredActionAlias := "UPDATE_PASSWORD" + maxAuthAgeConfig := "3600" + + resource.Test(t, resource.TestCase{ + ProviderFactories: testAccProviderFactories, + PreCheck: func() { testAccPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testKeycloakRequiredAction_withConfig(realmName, requiredActionAlias, 37, maxAuthAgeConfig), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakRequiresActionExists(realmName, requiredActionAlias), + resource.TestCheckResourceAttr("keycloak_required_action.required_action", "realm_id", realmName), + resource.TestCheckResourceAttr("keycloak_required_action.required_action", "config.%", "1"), + resource.TestCheckResourceAttr("keycloak_required_action.required_action", "config.max_auth_age", maxAuthAgeConfig), + ), + }, + }, + }) +} + func TestAccKeycloakRequiredAction_unregisteredAction(t *testing.T) { realmName := acctest.RandomWithPrefix("tf-acc") requiredActionAlias := "webauthn-register" @@ -128,6 +150,25 @@ resource "keycloak_required_action" "required_action" { `, realm, requiredActionAlias, priority) } +func testKeycloakRequiredAction_withConfig(realm, requiredActionAlias string, priority int, maxAuthAgeConfig string) string { + return fmt.Sprintf(` +resource "keycloak_realm" "realm" { + realm = "%s" +} +resource "keycloak_required_action" "required_action" { + realm_id = "${keycloak_realm.realm.realm}" + alias = "%s" + default_action = true + enabled = true + name = "My required Action" + priority = %d + config = { + max_auth_age = "%s" + } +} + `, realm, requiredActionAlias, priority, maxAuthAgeConfig) +} + func testKeycloakRequiredAction_import(realm, requiredActionAlias string) string { return fmt.Sprintf(` resource "keycloak_realm" "realm" {