From 3e8a3e68fa1685859f1a9dc3e2e80502e4cb344b Mon Sep 17 00:00:00 2001 From: tomrutsaert Date: Wed, 17 Jul 2019 15:59:54 +0200 Subject: [PATCH] allow extra config for keycloak_custom_user_federation resource (#134) --- .../CustomUserStorageProviderFactory.kt | 29 ++++++++-- docker-compose.yml | 6 +- keycloak/custom_user_federation.go | 30 ++++++---- ...esource_keycloak_custom_user_federation.go | 15 +++++ ...ce_keycloak_custom_user_federation_test.go | 56 +++++++++++++++++++ 5 files changed, 117 insertions(+), 19 deletions(-) diff --git a/custom-user-federation-example/src/main/kotlin/com/github/mrparkers/keycloak/CustomUserStorageProviderFactory.kt b/custom-user-federation-example/src/main/kotlin/com/github/mrparkers/keycloak/CustomUserStorageProviderFactory.kt index b6b2ba9b3..e3ac34967 100644 --- a/custom-user-federation-example/src/main/kotlin/com/github/mrparkers/keycloak/CustomUserStorageProviderFactory.kt +++ b/custom-user-federation-example/src/main/kotlin/com/github/mrparkers/keycloak/CustomUserStorageProviderFactory.kt @@ -2,15 +2,32 @@ package com.github.mrparkers.keycloak import org.keycloak.component.ComponentModel import org.keycloak.models.KeycloakSession +import org.keycloak.provider.ProviderConfigProperty import org.keycloak.storage.UserStorageProviderFactory class CustomUserStorageProviderFactory : UserStorageProviderFactory { - override fun getId(): String = "custom" + override fun getId(): String = "custom" - override fun init(config: org.keycloak.Config.Scope) { - super.init(config) - } + override fun init(config: org.keycloak.Config.Scope) { + super.init(config) + } - override fun create(session: KeycloakSession, model: ComponentModel): CustomUserStorageProvider = - CustomUserStorageProvider(session, model) + override fun create(session: KeycloakSession, model: ComponentModel): CustomUserStorageProvider = + CustomUserStorageProvider(session, model) + + override fun getConfigProperties(): List = configPropertyList + + companion object { + private val configPropertyList = ArrayList() + + init { + val property = ProviderConfigProperty() + property.setName("dummyConfig") + property.setLabel("Dummy Config") + property.setDefaultValue("") + property.setType(ProviderConfigProperty.STRING_TYPE) + property.setHelpText("Dummy config for testing") + configPropertyList.add(property) + } + } } diff --git a/docker-compose.yml b/docker-compose.yml index 25d434dd1..80bfe172f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,9 +24,9 @@ services: environment: - DB_VENDOR=POSTGRES - KEYCLOAK_LOGLEVEL=DEBUG - - POSTGRES_USER=keycloak - - POSTGRES_DATABASE=keycloak - - POSTGRES_PASSWORD=password + - DB_USER=keycloak + - DB_DATABASE=keycloak + - DB_PASSWORD=password - KEYCLOAK_USER=keycloak - KEYCLOAK_PASSWORD=password - POSTGRES_PORT_5432_TCP_ADDR=postgres diff --git a/keycloak/custom_user_federation.go b/keycloak/custom_user_federation.go index 9ebf1e400..4b49111e2 100644 --- a/keycloak/custom_user_federation.go +++ b/keycloak/custom_user_federation.go @@ -15,6 +15,8 @@ type CustomUserFederation struct { Priority int CachePolicy string + + Config map[string][]string } var ( @@ -22,17 +24,16 @@ var ( ) func convertFromCustomUserFederationToComponent(custom *CustomUserFederation) *component { - componentConfig := map[string][]string{ - "cachePolicy": { - custom.CachePolicy, - }, - "enabled": { - strconv.FormatBool(custom.Enabled), - }, - "priority": { - strconv.Itoa(custom.Priority), - }, + componentConfig := make(map[string][]string) + + if custom.Config != nil { + for k, j := range custom.Config { + componentConfig[k] = append(componentConfig[k], j[0]) + } } + componentConfig["cachePolicy"] = append(componentConfig["cachePolicy"], custom.CachePolicy) + componentConfig["enabled"] = append(componentConfig["enabled"], strconv.FormatBool(custom.Enabled)) + componentConfig["priority"] = append(componentConfig["priority"], strconv.Itoa(custom.Priority)) return &component{ Id: custom.Id, @@ -55,6 +56,13 @@ func convertFromComponentToCustomUserFederation(component *component) (*CustomUs return nil, err } + config := make(map[string][]string) + for k := range component.Config { + if k != "enabled" && k != "priority" && k != "cachePolicy" { + config[k] = append(config[k], component.getConfig(k)) + } + } + custom := &CustomUserFederation{ Id: component.Id, Name: component.Name, @@ -65,6 +73,8 @@ func convertFromComponentToCustomUserFederation(component *component) (*CustomUs Priority: priority, CachePolicy: component.getConfig("cachePolicy"), + + Config: config, } return custom, nil diff --git a/provider/resource_keycloak_custom_user_federation.go b/provider/resource_keycloak_custom_user_federation.go index 914adf12c..8e46d98da 100644 --- a/provider/resource_keycloak_custom_user_federation.go +++ b/provider/resource_keycloak_custom_user_federation.go @@ -56,11 +56,23 @@ func resourceKeycloakCustomUserFederation() *schema.Resource { Default: "DEFAULT", ValidateFunc: validation.StringInSlice(keycloakUserFederationCachePolicies, false), }, + + "config": { + Type: schema.TypeMap, + Optional: true, + }, }, } } func getCustomUserFederationFromData(data *schema.ResourceData) *keycloak.CustomUserFederation { + config := map[string][]string{} + if v, ok := data.GetOk("config"); ok { + for key, value := range v.(map[string]interface{}) { + config[key] = strings.Split(value.(string), ",") + } + } + return &keycloak.CustomUserFederation{ Id: data.Id(), Name: data.Get("name").(string), @@ -71,6 +83,8 @@ func getCustomUserFederationFromData(data *schema.ResourceData) *keycloak.Custom Priority: data.Get("priority").(int), CachePolicy: data.Get("cache_policy").(string), + + Config: config, } } @@ -85,6 +99,7 @@ func setCustomUserFederationData(data *schema.ResourceData, custom *keycloak.Cus data.Set("priority", custom.Priority) data.Set("cache_policy", custom.CachePolicy) + data.Set("config", custom.Config) } func resourceKeycloakCustomUserFederationCreate(data *schema.ResourceData, meta interface{}) error { diff --git a/provider/resource_keycloak_custom_user_federation_test.go b/provider/resource_keycloak_custom_user_federation_test.go index 0ad638de8..e046ceb76 100644 --- a/provider/resource_keycloak_custom_user_federation_test.go +++ b/provider/resource_keycloak_custom_user_federation_test.go @@ -36,6 +36,27 @@ func TestAccKeycloakCustomUserFederation_basic(t *testing.T) { }) } +func TestAccKeycloakCustomUserFederation_customConfig(t *testing.T) { + skipIfEnvSet(t, "CI") // temporary while I figure out how to load this custom provider in CI + + realmName := "terraform-" + acctest.RandString(10) + name := "terraform-" + acctest.RandString(10) + configValue := "value-" + acctest.RandString(10) + providerId := "custom" + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakCustomUserFederationDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakCustomUserFederation_customConfig(realmName, name, providerId, configValue), + Check: testAccCheckKeycloakCustomUserFederationExistsWithCustomConfig("keycloak_custom_user_federation.custom", configValue), + }, + }, + }) +} + func TestAccKeycloakCustomUserFederation_createAfterManualDestroy(t *testing.T) { skipIfEnvSet(t, "CI") // temporary while I figure out how to load this custom provider in CI @@ -99,6 +120,21 @@ func testAccCheckKeycloakCustomUserFederationExists(resourceName string) resourc } } +func testAccCheckKeycloakCustomUserFederationExistsWithCustomConfig(resourceName, customConfigValue string) resource.TestCheckFunc { + return func(s *terraform.State) error { + fetchedFederation, err := getCustomUserFederationFromState(s, resourceName) + if err != nil { + return err + } + + if len(fetchedFederation.Config["dummyConfig"]) <= 0 || fetchedFederation.Config["dummyConfig"][0] != customConfigValue { + return fmt.Errorf("expected user federation provider to have config with a custom key 'dummyConfig' with a value %s", customConfigValue) + } + + return nil + } +} + func testAccCheckKeycloakCustomUserFederationFetch(resourceName string, federation *keycloak.CustomUserFederation) resource.TestCheckFunc { return func(s *terraform.State) error { fetchedFederation, err := getCustomUserFederationFromState(s, resourceName) @@ -169,3 +205,23 @@ resource "keycloak_custom_user_federation" "custom" { } `, realm, name, providerId) } + +func testKeycloakCustomUserFederation_customConfig(realm, name, providerId, customConfigValue string) string { + return fmt.Sprintf(` +resource "keycloak_realm" "realm" { + realm = "%s" +} + +resource "keycloak_custom_user_federation" "custom" { + name = "%s" + realm_id = "${keycloak_realm.realm.id}" + provider_id = "%s" + + enabled = true + + config = { + dummyConfig = "%s" + } +} + `, realm, name, providerId, customConfigValue) +}