From 963a75b8161aa1213b8fb6d9993277ef93c59c21 Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 3 Oct 2019 16:45:37 +0200 Subject: [PATCH] new data_source: keycloak_realm (#160) --- docs/data_sources/keycloak_realm.md | 30 ++ mkdocs.yml | 1 + provider/data_source_keycloak_realm.go | 318 ++++++++++++++++++++ provider/data_source_keycloak_realm_test.go | 62 ++++ provider/provider.go | 1 + 5 files changed, 412 insertions(+) create mode 100644 docs/data_sources/keycloak_realm.md create mode 100644 provider/data_source_keycloak_realm.go create mode 100644 provider/data_source_keycloak_realm_test.go diff --git a/docs/data_sources/keycloak_realm.md b/docs/data_sources/keycloak_realm.md new file mode 100644 index 000000000..f373cb66a --- /dev/null +++ b/docs/data_sources/keycloak_realm.md @@ -0,0 +1,30 @@ +# keycloak_realm data source + +This data source can be used to fetch properties of a Keycloak realm for +usage with other resources. + +### Example Usage + +```hcl +data "keycloak_realm" "realm" { + realm = "my-realm" +} + +# use the data source + +resource "keycloak_role" "group" { + realm_id = "${data.keycloak_realm.id}" + name = "group" +} + +``` + +### Argument Reference + +The following arguments are supported: + +- `realm` - (Required) The realm name. + +### Attributes Reference + +See the docs for the [`keycloak_realm` resource](../resources/keycloak_realm.md) for details on the exported attributes. diff --git a/mkdocs.yml b/mkdocs.yml index ba7350a70..e21a5ede3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,6 +4,7 @@ repo_url: https://github.com/mrparkers/terraform-provider-keycloak nav: - Getting Started: index.md - Data Sources: + - keycloak_realm: data_sources/keycloak_realm.md - keycloak_realm_keys: data_sources/keycloak_realm_keys.md - keycloak_role: data_sources/keycloak_role.md - Resources: diff --git a/provider/data_source_keycloak_realm.go b/provider/data_source_keycloak_realm.go new file mode 100644 index 000000000..225c9d5f6 --- /dev/null +++ b/provider/data_source_keycloak_realm.go @@ -0,0 +1,318 @@ +package provider + +import ( + "github.com/hashicorp/terraform/helper/schema" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" +) + +func dataSourceKeycloakRealm() *schema.Resource { + return &schema.Resource{ + Read: dataSourceKeycloakRealmRead, + Schema: map[string]*schema.Schema{ + "realm": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "display_name": { + Type: schema.TypeString, + Computed: true, + }, + + // Login Config + + "registration_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "registration_email_as_username": { + Type: schema.TypeBool, + Computed: true, + }, + "edit_username_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "reset_password_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "remember_me": { + Type: schema.TypeBool, + Computed: true, + }, + "verify_email": { + Type: schema.TypeBool, + Computed: true, + }, + "login_with_email_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + "duplicate_emails_allowed": { + Type: schema.TypeBool, + Computed: true, + }, + + //Smtp server + + "smtp_server": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "starttls": { + Type: schema.TypeBool, + Computed: true, + }, + "port": { + Type: schema.TypeString, + Computed: true, + }, + "host": { + Type: schema.TypeString, + Computed: true, + }, + "reply_to": { + Type: schema.TypeString, + Computed: true, + }, + "reply_to_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "from": { + Type: schema.TypeString, + Computed: true, + }, + "from_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "envelope_from": { + Type: schema.TypeString, + Computed: true, + }, + "ssl": { + Type: schema.TypeBool, + Computed: true, + }, + "auth": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Computed: true, + }, + "password": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + }, + }, + }, + }, + }, + }, + + // Themes + + "login_theme": { + Type: schema.TypeString, + Computed: true, + }, + "account_theme": { + Type: schema.TypeString, + Computed: true, + }, + "admin_theme": { + Type: schema.TypeString, + Computed: true, + }, + "email_theme": { + Type: schema.TypeString, + Computed: true, + }, + + // Tokens + + "refresh_token_max_reuse": { + Type: schema.TypeInt, + Computed: true, + }, + "sso_session_idle_timeout": { + Type: schema.TypeString, + Computed: true, + }, + "sso_session_max_lifespan": { + Type: schema.TypeString, + Computed: true, + }, + "offline_session_idle_timeout": { + Type: schema.TypeString, + Computed: true, + }, + "offline_session_max_lifespan": { + Type: schema.TypeString, + Computed: true, + }, + "access_token_lifespan": { + Type: schema.TypeString, + Computed: true, + }, + "access_token_lifespan_for_implicit_flow": { + Type: schema.TypeString, + Computed: true, + }, + "access_code_lifespan": { + Type: schema.TypeString, + Computed: true, + }, + "access_code_lifespan_login": { + Type: schema.TypeString, + Computed: true, + }, + "access_code_lifespan_user_action": { + Type: schema.TypeString, + Computed: true, + }, + "action_token_generated_by_user_lifespan": { + Type: schema.TypeString, + Computed: true, + }, + "action_token_generated_by_admin_lifespan": { + Type: schema.TypeString, + Computed: true, + }, + + //internationalization + "internationalization": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "supported_locales": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Computed: true, + }, + "default_locale": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + //Security Defenses + "security_defenses": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "headers": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "x_frame_options": { + Type: schema.TypeString, + Computed: true, + }, + "content_security_policy": { + Type: schema.TypeString, + Computed: true, + }, + "content_security_policy_report_only": { + Type: schema.TypeString, + Computed: true, + }, + "x_content_type_options": { + Type: schema.TypeString, + Computed: true, + }, + "x_robots_tag": { + Type: schema.TypeString, + Computed: true, + }, + "x_xss_protection": { + Type: schema.TypeString, + Computed: true, + }, + "strict_transport_security": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "password_policy": { + Type: schema.TypeString, + Description: "String that represents the passwordPolicies that are in place. Each policy is separated with \" and \". Supported policies can be found in the server-info providers page. example: \"upperCase(1) and length(8) and forceExpiredPasswordChange(365) and notUsername(undefined)\"", + Computed: true, + }, + + //flow bindings + "browser_flow": { + Type: schema.TypeString, + Description: "Which flow should be used for BrowserFlow", + Computed: true, + }, + "registration_flow": { + Type: schema.TypeString, + Description: "Which flow should be used for RegistrationFlow", + Computed: true, + }, + "direct_grant_flow": { + Type: schema.TypeString, + Description: "Which flow should be used for DirectGrantFlow", + Computed: true, + }, + "reset_credentials_flow": { + Type: schema.TypeString, + Description: "Which flow should be used for ResetCredentialsFlow", + Computed: true, + }, + "client_authentication_flow": { + Type: schema.TypeString, + Description: "Which flow should be used for ClientAuthenticationFlow", + Computed: true, + }, + "docker_authentication_flow": { + Type: schema.TypeString, + Description: "Which flow should be used for DockerAuthenticationFlow", + Computed: true, + }, + }, + } +} + +func dataSourceKeycloakRealmRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm").(string) + + realm, err := keycloakClient.GetRealm(realmId) + if err != nil { + return err + } + + setRealmData(data, realm) + + return nil +} diff --git a/provider/data_source_keycloak_realm_test.go b/provider/data_source_keycloak_realm_test.go new file mode 100644 index 000000000..7c73c4b29 --- /dev/null +++ b/provider/data_source_keycloak_realm_test.go @@ -0,0 +1,62 @@ +package provider + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" +) + +func TestAccKeycloakDataSourceRealm_basic(t *testing.T) { + realm := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakRealmDestroy(), + Steps: []resource.TestStep{ + { + Config: testDataSourceKeycloakRealm_basic(realm), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakRealmExists("keycloak_realm.realm"), + ), + }, + }, + }) +} + +func testAccCheckDataKeycloakRealm(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) + } + + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + realmId := rs.Primary.Attributes["realm_id"] + name := rs.Primary.Attributes["display_name"] + + realm, err := keycloakClient.GetRealm(realmId) + if err != nil { + return err + } + + if realm.DisplayName != name { + return fmt.Errorf("expected realm with ID %s to have display_name %s, but got %s", realmId, name, realm.DisplayName) + } + + return nil + } +} + +func testDataSourceKeycloakRealm_basic(realm string) string { + return fmt.Sprintf(` +resource "keycloak_realm" "realm" { + realm = "%s" + display_name = "foo" +}`, realm) +} diff --git a/provider/provider.go b/provider/provider.go index 06aa3b1e1..97c17aa86 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -10,6 +10,7 @@ func KeycloakProvider() *schema.Provider { DataSourcesMap: map[string]*schema.Resource{ "keycloak_openid_client": dataSourceKeycloakOpenidClient(), "keycloak_openid_client_authorization_policy": dataSourceKeycloakOpenidClientAuthorizationPolicy(), + "keycloak_realm": dataSourceKeycloakRealm(), "keycloak_realm_keys": dataSourceKeycloakRealmKeys(), "keycloak_role": dataSourceKeycloakRole(), },