From 3dd442f7635a5cdb3b7d4aac059af82256262f07 Mon Sep 17 00:00:00 2001 From: Andrew Chubatiuk Date: Thu, 25 Apr 2019 18:24:46 +0300 Subject: [PATCH 01/47] initial commit --- keycloak/openid_client.go | 17 ++++++-- provider/keycloak_openid_client.go | 67 ++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index e97985e6..aa8ad949 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -4,11 +4,21 @@ import ( "fmt" ) -type openidClientSecret struct { +type OpenidClientSecret struct { Type string `json:"type"` Value string `json:"value"` } +type OpenidClientResource struct { + DisplayName string `json:"display_name"` + Name string `json:"name"` + Uris []string `json:"uris"` + IconUri string `json:"icon_uri"` + OwnerManagedAccess bool `json:"owner_managed_access"` + Scopes []string `json:"scopes"` + Attributes map[string][]string `json:"attributes"` +} + type OpenidClient struct { Id string `json:"id,omitempty"` ClientId string `json:"clientId"` @@ -29,6 +39,7 @@ type OpenidClient struct { ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` + AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` ValidRedirectUris []string `json:"redirectUris"` WebOrigins []string `json:"webOrigins"` @@ -66,7 +77,7 @@ func (keycloakClient *KeycloakClient) NewOpenidClient(client *OpenidClient) erro func (keycloakClient *KeycloakClient) GetOpenidClient(realmId, id string) (*OpenidClient, error) { var client OpenidClient - var clientSecret openidClientSecret + var clientSecret OpenidClientSecret err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), &client) if err != nil { @@ -86,7 +97,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClient(realmId, id string) (*Open func (keycloakClient *KeycloakClient) GetOpenidClientByClientId(realmId, clientId string) (*OpenidClient, error) { var clients []OpenidClient - var clientSecret openidClientSecret + var clientSecret OpenidClientSecret err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients?clientId=%s", realmId, clientId), &clients) if err != nil { diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 66fb7f82..710c06b0 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -88,11 +88,51 @@ func resourceKeycloakOpenidClient() *schema.Resource { Set: schema.HashString, Optional: true, }, + "resource": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "display_name": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "uris": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "icon_uri": { + Type: schema.TypeString, + Optional: true, + }, + "owner_managed_access": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "scopes": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "attributes": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + }, + }, + }, }, } } -func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient { +func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient, []keycloak.OpenidClientResource { validRedirectUris := make([]string, 0) webOrigins := make([]string, 0) @@ -124,6 +164,27 @@ func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient { WebOrigins: webOrigins, } + resources := []keycloak.OpenidClientResource{} + + if v, ok := data.GetOk("resource"); ok { + openidClient.AuthorizationServicesEnabled = true + for resourceData := v.(*schema.Set).List() { + resource := keycloak.OpenidClientResource{ + DisplayName: resourceData.Get("display_name").(string), + Name: resourceData.Get("name").(string), + IconUri: resourceData.Get("icon_uri").(string), + OwnerManagedAccess: resourceData.Get("owner_managed_access").(bool), + Uris: resourceData.Get("uris").(map[string]string), + Scopes: resourceData.Get("scopes").(map[string]string), + Attributes: resourceData.Get("attributes").(map[string][]string), + } + resources.append(resources, resource) + } + + } else { + openidClient.AuthorizationServicesEnabled = false + } + // access type if accessType := data.Get("access_type").(string); accessType == "PUBLIC" { openidClient.PublicClient = true @@ -131,10 +192,10 @@ func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient { openidClient.BearerOnly = true } - return openidClient + return openidClient, resources } -func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient) { +func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, resources []keycloak.OpenidClientResource) { data.SetId(client.Id) data.Set("client_id", client.ClientId) From 6909b202c40bf7c5d34d3f78de7a0338077c9ee7 Mon Sep 17 00:00:00 2001 From: Andrew Chubatiuk Date: Fri, 26 Apr 2019 13:40:02 +0300 Subject: [PATCH 02/47] go fmt --- keycloak/openid_client.go | 63 +++++++++++++++++++---- provider/keycloak_openid_client.go | 82 +++++++++++++++++++++--------- 2 files changed, 111 insertions(+), 34 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index aa8ad949..7cd44074 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -10,15 +10,18 @@ type OpenidClientSecret struct { } type OpenidClientResource struct { - DisplayName string `json:"display_name"` - Name string `json:"name"` - Uris []string `json:"uris"` - IconUri string `json:"icon_uri"` - OwnerManagedAccess bool `json:"owner_managed_access"` - Scopes []string `json:"scopes"` - Attributes map[string][]string `json:"attributes"` + Id string `json:"-"` + DisplayName string `json:"display_name"` + Name string `json:"name"` + Uris []string `json:"uris"` + IconUri string `json:"icon_uri"` + OwnerManagedAccess bool `json:"owner_managed_access"` + Scopes []string `json:"scopes"` + Attributes map[string][]string `json:"attributes"` } +type OpenidClientResources []OpenidClientResource + type OpenidClient struct { Id string `json:"id,omitempty"` ClientId string `json:"clientId"` @@ -35,16 +38,54 @@ type OpenidClient struct { PublicClient bool `json:"publicClient"` BearerOnly bool `json:"bearerOnly"` - StandardFlowEnabled bool `json:"standardFlowEnabled"` - ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` - DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` - ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` + StandardFlowEnabled bool `json:"standardFlowEnabled"` + ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` + DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` + ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` ValidRedirectUris []string `json:"redirectUris"` WebOrigins []string `json:"webOrigins"` } +func (keycloakClient *KeycloakClient) NewOpenidClientResource(client *OpenidClient, resource *OpenidClientResource) error { + _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", client.RealmId, client.Id), resource) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientResource(realm string, clientId string, resourceId string) (*OpenidClientResource, error) { + var clientResource OpenidClientResource + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, clientId, resourceId), &clientResource) + if err != nil { + return nil, err + } + return &clientResource, nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientResources(realm string, clientId string) (*OpenidClientResources, error) { + var clientResources *OpenidClientResources + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", realm, clientId), &clientResources) + if err != nil { + return nil, err + } + return clientResources, nil +} + +func (keycloakClient *KeycloakClient) UpdateOpenidClientResource(client *OpenidClient, resource *OpenidClientResource) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", client.RealmId, client.Id, resource.Id), resource) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientResource(realmId, clientId string, resourceId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realmId, clientId, resourceId)) +} + func (keycloakClient *KeycloakClient) ValidateOpenidClient(client *OpenidClient) error { if client.BearerOnly && (client.StandardFlowEnabled || client.ImplicitFlowEnabled || client.DirectAccessGrantsEnabled || client.ServiceAccountsEnabled) { return fmt.Errorf("validation error: Keycloak cannot issue tokens for bearer-only clients; no oauth2 flows can be enabled for this client") diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 710c06b0..a7268dd0 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -103,7 +103,7 @@ func resourceKeycloakOpenidClient() *schema.Resource { }, "uris": { Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, "icon_uri": { @@ -111,13 +111,13 @@ func resourceKeycloakOpenidClient() *schema.Resource { Optional: true, }, "owner_managed_access": { - Type: schema.TypeBool, + Type: schema.TypeBool, Optional: true, - Default: false, + Default: false, }, "scopes": { Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, "attributes": { @@ -127,12 +127,12 @@ func resourceKeycloakOpenidClient() *schema.Resource { }, }, }, - }, + }, }, } } -func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient, []keycloak.OpenidClientResource { +func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResources) { validRedirectUris := make([]string, 0) webOrigins := make([]string, 0) @@ -164,21 +164,22 @@ func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient, WebOrigins: webOrigins, } - resources := []keycloak.OpenidClientResource{} + var resources keycloak.OpenidClientResources if v, ok := data.GetOk("resource"); ok { openidClient.AuthorizationServicesEnabled = true - for resourceData := v.(*schema.Set).List() { + for _, d := range v.(*schema.Set).List() { + resourceData := d.(map[string]interface{}) resource := keycloak.OpenidClientResource{ - DisplayName: resourceData.Get("display_name").(string), - Name: resourceData.Get("name").(string), - IconUri: resourceData.Get("icon_uri").(string), - OwnerManagedAccess: resourceData.Get("owner_managed_access").(bool), - Uris: resourceData.Get("uris").(map[string]string), - Scopes: resourceData.Get("scopes").(map[string]string), - Attributes: resourceData.Get("attributes").(map[string][]string), + DisplayName: resourceData["display_name"].(string), + Name: resourceData["name"].(string), + IconUri: resourceData["icon_uri"].(string), + OwnerManagedAccess: resourceData["owner_managed_access"].(bool), + Uris: resourceData["uris"].([]string), + Scopes: resourceData["scopes"].([]string), + Attributes: resourceData["attributes"].(map[string][]string), } - resources.append(resources, resource) + resources = append(resources, resource) } } else { @@ -192,10 +193,10 @@ func getOpenidClientFromData(data *schema.ResourceData) *keycloak.OpenidClient, openidClient.BearerOnly = true } - return openidClient, resources + return openidClient, &resources } -func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, resources []keycloak.OpenidClientResource) { +func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, resources *keycloak.OpenidClientResources) { data.SetId(client.Id) data.Set("client_id", client.ClientId) @@ -219,12 +220,28 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien } else { data.Set("access_type", "CONFIDENTIAL") } + + resourcesData := make(map[string]interface{}) + + for _, resource := range *resources { + resourceData := map[string]interface{}{ + "display_name": resource.DisplayName, + "name": resource.Name, + "uris": resource.Uris, + "icon_uri": resource.IconUri, + "owner_managed_access": resource.OwnerManagedAccess, + "scopes": resource.Scopes, + "attributes": resource.Attributes, + } + resourcesData[resource.Id] = resourceData + } + data.Set("resources", resourcesData) } func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client := getOpenidClientFromData(data) + client, resources := getOpenidClientFromData(data) err := keycloakClient.ValidateOpenidClient(client) if err != nil { @@ -236,7 +253,14 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - setOpenidClientData(data, client) + for _, resource := range *resources { + err = keycloakClient.NewOpenidClientResource(client, &resource) + if err != nil { + return err + } + } + + setOpenidClientData(data, client, resources) return resourceKeycloakOpenidClientRead(data, meta) } @@ -252,7 +276,12 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ return handleNotFoundError(err, data) } - setOpenidClientData(data, client) + resources, err := keycloakClient.GetOpenidClientResources(realmId, id) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientData(data, client, resources) return nil } @@ -260,7 +289,7 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client := getOpenidClientFromData(data) + client, resources := getOpenidClientFromData(data) err := keycloakClient.ValidateOpenidClient(client) if err != nil { @@ -272,7 +301,14 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac return err } - setOpenidClientData(data, client) + for _, resource := range *resources { + err = keycloakClient.UpdateOpenidClientResource(client, &resource) + if err != nil { + return err + } + } + + setOpenidClientData(data, client, resources) return nil } From 853524dfb80970ea6523e582ee98ed4d01744761 Mon Sep 17 00:00:00 2001 From: Andrew Chubatiuk Date: Fri, 26 Apr 2019 14:21:25 +0300 Subject: [PATCH 03/47] fixed resource body params --- keycloak/openid_client.go | 4 ++-- provider/keycloak_openid_client.go | 28 +++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 7cd44074..23600499 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -11,11 +11,11 @@ type OpenidClientSecret struct { type OpenidClientResource struct { Id string `json:"-"` - DisplayName string `json:"display_name"` + DisplayName string `json:"displayName"` Name string `json:"name"` Uris []string `json:"uris"` IconUri string `json:"icon_uri"` - OwnerManagedAccess bool `json:"owner_managed_access"` + OwnerManagedAccess bool `json:"ownerManagedAccess"` Scopes []string `json:"scopes"` Attributes map[string][]string `json:"attributes"` } diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index a7268dd0..eb81a3f7 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -133,8 +133,8 @@ func resourceKeycloakOpenidClient() *schema.Resource { } func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResources) { - validRedirectUris := make([]string, 0) - webOrigins := make([]string, 0) + var validRedirectUris []string + var webOrigins []string if v, ok := data.GetOk("valid_redirect_uris"); ok { for _, validRedirectUri := range v.(*schema.Set).List() { @@ -170,14 +170,32 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, openidClient.AuthorizationServicesEnabled = true for _, d := range v.(*schema.Set).List() { resourceData := d.(map[string]interface{}) + var uris []string + var scopes []string + var attributes map[string][]string + if v, ok := data.GetOk("uris"); ok { + for _, uri := range v.(*schema.Set).List() { + uris = append(uris, uri.(string)) + } + } + if v, ok := data.GetOk("scopes"); ok { + for _, scope := range v.(*schema.Set).List() { + scopes = append(scopes, scope.(string)) + } + } + if v, ok := data.GetOk("attribites"); ok { + for key, value := range v.(map[string]string) { + attributes[key] = strings.Split(value, ",") + } + } resource := keycloak.OpenidClientResource{ DisplayName: resourceData["display_name"].(string), Name: resourceData["name"].(string), IconUri: resourceData["icon_uri"].(string), OwnerManagedAccess: resourceData["owner_managed_access"].(bool), - Uris: resourceData["uris"].([]string), - Scopes: resourceData["scopes"].([]string), - Attributes: resourceData["attributes"].(map[string][]string), + Uris: uris, + Scopes: scopes, + Attributes: attributes, } resources = append(resources, resource) } From 5555d95e40a30a3457b2f437f42475a10cb2eda8 Mon Sep 17 00:00:00 2001 From: Andrew Chubatiuk Date: Fri, 26 Apr 2019 17:20:58 +0300 Subject: [PATCH 04/47] fixed resource id --- keycloak/custom_user_federation.go | 2 +- keycloak/group.go | 2 +- keycloak/identity_provider.go | 2 +- keycloak/identity_provider_mapper.go | 2 +- keycloak/keycloak_client.go | 10 +++++----- keycloak/ldap_full_name_mapper.go | 2 +- keycloak/ldap_group_mapper.go | 2 +- .../ldap_msad_user_account_control_mapper.go | 2 +- keycloak/ldap_user_attribute_mapper.go | 2 +- keycloak/ldap_user_federation.go | 2 +- keycloak/openid_audience_protocol_mapper.go | 2 +- keycloak/openid_client.go | 11 ++++++++--- keycloak/openid_client_scope.go | 2 +- keycloak/openid_full_name_protocol_mapper.go | 2 +- .../openid_group_membership_protocol_mapper.go | 2 +- .../openid_hardcoded_claim_protocol_mapper.go | 2 +- .../openid_user_attribute_protocol_mapper.go | 2 +- keycloak/openid_user_property_protocol_mapper.go | 2 +- keycloak/realm.go | 2 +- keycloak/saml_client.go | 2 +- keycloak/saml_user_attribute_protocol_mapper.go | 2 +- keycloak/saml_user_property_protocol_mapper.go | 2 +- keycloak/user.go | 2 +- provider/keycloak_openid_client.go | 16 +++++++++++----- 24 files changed, 45 insertions(+), 34 deletions(-) diff --git a/keycloak/custom_user_federation.go b/keycloak/custom_user_federation.go index 20c6f19f..313115e6 100644 --- a/keycloak/custom_user_federation.go +++ b/keycloak/custom_user_federation.go @@ -85,7 +85,7 @@ func (keycloakClient *KeycloakClient) ValidateCustomUserFederation(custom *Custo } func (keycloakClient *KeycloakClient) NewCustomUserFederation(customUserFederation *CustomUserFederation) error { - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", customUserFederation.RealmId), convertFromCustomUserFederationToComponent(customUserFederation)) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", customUserFederation.RealmId), convertFromCustomUserFederationToComponent(customUserFederation)) if err != nil { return err } diff --git a/keycloak/group.go b/keycloak/group.go index 370e028c..0a98b7fa 100644 --- a/keycloak/group.go +++ b/keycloak/group.go @@ -79,7 +79,7 @@ func (keycloakClient *KeycloakClient) NewGroup(group *Group) error { createGroupUrl = fmt.Sprintf("/realms/%s/groups/%s/children", group.RealmId, group.ParentId) } - location, err := keycloakClient.post(createGroupUrl, group) + _, location, err := keycloakClient.post(createGroupUrl, group) if err != nil { return err } diff --git a/keycloak/identity_provider.go b/keycloak/identity_provider.go index f536d55b..b01a1af6 100644 --- a/keycloak/identity_provider.go +++ b/keycloak/identity_provider.go @@ -53,7 +53,7 @@ type IdentityProvider struct { func (keycloakClient *KeycloakClient) NewIdentityProvider(identityProvider *IdentityProvider) error { log.Printf("[WARN] Realm: %s", identityProvider.Realm) - _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/identity-provider/instances", identityProvider.Realm), identityProvider) + _, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/identity-provider/instances", identityProvider.Realm), identityProvider) if err != nil { return err } diff --git a/keycloak/identity_provider_mapper.go b/keycloak/identity_provider_mapper.go index a90d5d76..8151850e 100644 --- a/keycloak/identity_provider_mapper.go +++ b/keycloak/identity_provider_mapper.go @@ -29,7 +29,7 @@ type IdentityProviderMapper struct { func (keycloakClient *KeycloakClient) NewIdentityProviderMapper(identityProviderMapper *IdentityProviderMapper) error { log.Printf("[WARN] Realm: %s", identityProviderMapper.Realm) - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers", identityProviderMapper.Realm, identityProviderMapper.IdentityProviderAlias), identityProviderMapper) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers", identityProviderMapper.Realm, identityProviderMapper.IdentityProviderAlias), identityProviderMapper) if err != nil { return err } diff --git a/keycloak/keycloak_client.go b/keycloak/keycloak_client.go index 91a6dfd6..b254f296 100644 --- a/keycloak/keycloak_client.go +++ b/keycloak/keycloak_client.go @@ -263,22 +263,22 @@ func (keycloakClient *KeycloakClient) get(path string, resource interface{}) err return json.Unmarshal(body, resource) } -func (keycloakClient *KeycloakClient) post(path string, requestBody interface{}) (string, error) { +func (keycloakClient *KeycloakClient) post(path string, requestBody interface{}) ([]byte, string, error) { resourceUrl := keycloakClient.baseUrl + apiUrl + path payload, err := json.Marshal(requestBody) if err != nil { - return "", err + return nil, "", err } request, err := http.NewRequest(http.MethodPost, resourceUrl, bytes.NewReader(payload)) if err != nil { - return "", err + return nil, "", err } - _, location, err := keycloakClient.sendRequest(request) + body, location, err := keycloakClient.sendRequest(request) - return location, err + return body, location, err } func (keycloakClient *KeycloakClient) put(path string, requestBody interface{}) error { diff --git a/keycloak/ldap_full_name_mapper.go b/keycloak/ldap_full_name_mapper.go index 68616f2b..9b9c5907 100644 --- a/keycloak/ldap_full_name_mapper.go +++ b/keycloak/ldap_full_name_mapper.go @@ -82,7 +82,7 @@ func (keycloakClient *KeycloakClient) ValidateLdapFullNameMapper(mapper *LdapFul } func (keycloakClient *KeycloakClient) NewLdapFullNameMapper(ldapFullNameMapper *LdapFullNameMapper) error { - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapFullNameMapper.RealmId), convertFromLdapFullNameMapperToComponent(ldapFullNameMapper)) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapFullNameMapper.RealmId), convertFromLdapFullNameMapperToComponent(ldapFullNameMapper)) if err != nil { return err } diff --git a/keycloak/ldap_group_mapper.go b/keycloak/ldap_group_mapper.go index b08dc239..c55a226a 100644 --- a/keycloak/ldap_group_mapper.go +++ b/keycloak/ldap_group_mapper.go @@ -153,7 +153,7 @@ func (keycloakClient *KeycloakClient) ValidateLdapGroupMapper(ldapGroupMapper *L } func (keycloakClient *KeycloakClient) NewLdapGroupMapper(ldapGroupMapper *LdapGroupMapper) error { - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapGroupMapper.RealmId), convertFromLdapGroupMapperToComponent(ldapGroupMapper)) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapGroupMapper.RealmId), convertFromLdapGroupMapperToComponent(ldapGroupMapper)) if err != nil { return err } diff --git a/keycloak/ldap_msad_user_account_control_mapper.go b/keycloak/ldap_msad_user_account_control_mapper.go index d63f53a6..45b2e816 100644 --- a/keycloak/ldap_msad_user_account_control_mapper.go +++ b/keycloak/ldap_msad_user_account_control_mapper.go @@ -46,7 +46,7 @@ func convertFromComponentToLdapMsadUserAccountControlMapper(component *component } func (keycloakClient *KeycloakClient) NewLdapMsadUserAccountControlMapper(ldapMsadUserAccountControlMapper *LdapMsadUserAccountControlMapper) error { - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapMsadUserAccountControlMapper.RealmId), convertFromLdapMsadUserAccountControlMapperToComponent(ldapMsadUserAccountControlMapper)) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapMsadUserAccountControlMapper.RealmId), convertFromLdapMsadUserAccountControlMapperToComponent(ldapMsadUserAccountControlMapper)) if err != nil { return err } diff --git a/keycloak/ldap_user_attribute_mapper.go b/keycloak/ldap_user_attribute_mapper.go index 0d9d917f..75ff1548 100644 --- a/keycloak/ldap_user_attribute_mapper.go +++ b/keycloak/ldap_user_attribute_mapper.go @@ -76,7 +76,7 @@ func convertFromComponentToLdapUserAttributeMapper(component *component, realmId } func (keycloakClient *KeycloakClient) NewLdapUserAttributeMapper(ldapUserAttributeMapper *LdapUserAttributeMapper) error { - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapUserAttributeMapper.RealmId), convertFromLdapUserAttributeMapperToComponent(ldapUserAttributeMapper)) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapUserAttributeMapper.RealmId), convertFromLdapUserAttributeMapperToComponent(ldapUserAttributeMapper)) if err != nil { return err } diff --git a/keycloak/ldap_user_federation.go b/keycloak/ldap_user_federation.go index 4528b13e..9a00d3b1 100644 --- a/keycloak/ldap_user_federation.go +++ b/keycloak/ldap_user_federation.go @@ -303,7 +303,7 @@ func (keycloakClient *KeycloakClient) NewLdapUserFederation(ldapUserFederation * return err } - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapUserFederation.RealmId), component) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapUserFederation.RealmId), component) if err != nil { return err } diff --git a/keycloak/openid_audience_protocol_mapper.go b/keycloak/openid_audience_protocol_mapper.go index 93eef654..6d8ed4a9 100644 --- a/keycloak/openid_audience_protocol_mapper.go +++ b/keycloak/openid_audience_protocol_mapper.go @@ -78,7 +78,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenIdAudienceProtocolMapper(realmId func (keycloakClient *KeycloakClient) NewOpenIdAudienceProtocolMapper(mapper *OpenIdAudienceProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 23600499..db2a1536 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -1,6 +1,7 @@ package keycloak import ( + "encoding/json" "fmt" ) @@ -10,7 +11,7 @@ type OpenidClientSecret struct { } type OpenidClientResource struct { - Id string `json:"-"` + Id string `json:"_id,omitempty"` DisplayName string `json:"displayName"` Name string `json:"name"` Uris []string `json:"uris"` @@ -49,7 +50,11 @@ type OpenidClient struct { } func (keycloakClient *KeycloakClient) NewOpenidClientResource(client *OpenidClient, resource *OpenidClientResource) error { - _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", client.RealmId, client.Id), resource) + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", client.RealmId, client.Id), resource) + if err != nil { + return err + } + err = json.Unmarshal(body, &resource) if err != nil { return err } @@ -106,7 +111,7 @@ func (keycloakClient *KeycloakClient) NewOpenidClient(client *OpenidClient) erro client.Protocol = "openid-connect" client.ClientAuthenticatorType = "client-secret" - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients", client.RealmId), client) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients", client.RealmId), client) if err != nil { return err } diff --git a/keycloak/openid_client_scope.go b/keycloak/openid_client_scope.go index 13d9b462..9c76d083 100644 --- a/keycloak/openid_client_scope.go +++ b/keycloak/openid_client_scope.go @@ -21,7 +21,7 @@ type OpenidClientScopeFilterFunc func(*OpenidClientScope) bool func (keycloakClient *KeycloakClient) NewOpenidClientScope(clientScope *OpenidClientScope) error { clientScope.Protocol = "openid-connect" - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/client-scopes", clientScope.RealmId), clientScope) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/client-scopes", clientScope.RealmId), clientScope) if err != nil { return err } diff --git a/keycloak/openid_full_name_protocol_mapper.go b/keycloak/openid_full_name_protocol_mapper.go index fa6c7f06..e78c5f8f 100644 --- a/keycloak/openid_full_name_protocol_mapper.go +++ b/keycloak/openid_full_name_protocol_mapper.go @@ -78,7 +78,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenIdFullNameProtocolMapper(realmId func (keycloakClient *KeycloakClient) NewOpenIdFullNameProtocolMapper(mapper *OpenIdFullNameProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/openid_group_membership_protocol_mapper.go b/keycloak/openid_group_membership_protocol_mapper.go index f5a0e900..1fc5c0ac 100644 --- a/keycloak/openid_group_membership_protocol_mapper.go +++ b/keycloak/openid_group_membership_protocol_mapper.go @@ -90,7 +90,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenIdGroupMembershipProtocolMapper( func (keycloakClient *KeycloakClient) NewOpenIdGroupMembershipProtocolMapper(mapper *OpenIdGroupMembershipProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/openid_hardcoded_claim_protocol_mapper.go b/keycloak/openid_hardcoded_claim_protocol_mapper.go index 31f879f1..0fe50d69 100644 --- a/keycloak/openid_hardcoded_claim_protocol_mapper.go +++ b/keycloak/openid_hardcoded_claim_protocol_mapper.go @@ -89,7 +89,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenIdHardcodedClaimProtocolMapper(r func (keycloakClient *KeycloakClient) NewOpenIdHardcodedClaimProtocolMapper(mapper *OpenIdHardcodedClaimProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/openid_user_attribute_protocol_mapper.go b/keycloak/openid_user_attribute_protocol_mapper.go index 4615a996..a91e591d 100644 --- a/keycloak/openid_user_attribute_protocol_mapper.go +++ b/keycloak/openid_user_attribute_protocol_mapper.go @@ -99,7 +99,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenIdUserAttributeProtocolMapper(re func (keycloakClient *KeycloakClient) NewOpenIdUserAttributeProtocolMapper(mapper *OpenIdUserAttributeProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/openid_user_property_protocol_mapper.go b/keycloak/openid_user_property_protocol_mapper.go index 522aaa66..c436b761 100644 --- a/keycloak/openid_user_property_protocol_mapper.go +++ b/keycloak/openid_user_property_protocol_mapper.go @@ -89,7 +89,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenIdUserPropertyProtocolMapper(rea func (keycloakClient *KeycloakClient) NewOpenIdUserPropertyProtocolMapper(mapper *OpenIdUserPropertyProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/realm.go b/keycloak/realm.go index 3671d8a1..cbb5426d 100644 --- a/keycloak/realm.go +++ b/keycloak/realm.go @@ -43,7 +43,7 @@ type Realm struct { } func (keycloakClient *KeycloakClient) NewRealm(realm *Realm) error { - _, err := keycloakClient.post("/realms", realm) + _, _, err := keycloakClient.post("/realms", realm) return err } diff --git a/keycloak/saml_client.go b/keycloak/saml_client.go index be060a12..002cb0e3 100644 --- a/keycloak/saml_client.go +++ b/keycloak/saml_client.go @@ -47,7 +47,7 @@ func (keycloakClient *KeycloakClient) NewSamlClient(client *SamlClient) error { client.Protocol = "saml" client.ClientAuthenticatorType = "client-secret" - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients", client.RealmId), client) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients", client.RealmId), client) if err != nil { return err } diff --git a/keycloak/saml_user_attribute_protocol_mapper.go b/keycloak/saml_user_attribute_protocol_mapper.go index 0cbee86d..979ff770 100644 --- a/keycloak/saml_user_attribute_protocol_mapper.go +++ b/keycloak/saml_user_attribute_protocol_mapper.go @@ -65,7 +65,7 @@ func (keycloakClient *KeycloakClient) DeleteSamlUserAttributeProtocolMapper(real func (keycloakClient *KeycloakClient) NewSamlUserAttributeProtocolMapper(mapper *SamlUserAttributeProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/saml_user_property_protocol_mapper.go b/keycloak/saml_user_property_protocol_mapper.go index 194fedea..6be3e410 100644 --- a/keycloak/saml_user_property_protocol_mapper.go +++ b/keycloak/saml_user_property_protocol_mapper.go @@ -65,7 +65,7 @@ func (keycloakClient *KeycloakClient) DeleteSamlUserPropertyProtocolMapper(realm func (keycloakClient *KeycloakClient) NewSamlUserPropertyProtocolMapper(mapper *SamlUserPropertyProtocolMapper) error { path := protocolMapperPath(mapper.RealmId, mapper.ClientId, mapper.ClientScopeId) - location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) + _, location, err := keycloakClient.post(path, mapper.convertToGenericProtocolMapper()) if err != nil { return err } diff --git a/keycloak/user.go b/keycloak/user.go index 4c36b3ed..2a4e9bd7 100644 --- a/keycloak/user.go +++ b/keycloak/user.go @@ -23,7 +23,7 @@ type PasswordCredentials struct { } func (keycloakClient *KeycloakClient) NewUser(user *User) error { - location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/users", user.RealmId), user) + _, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/users", user.RealmId), user) if err != nil { return err } diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index eb81a3f7..c6205064 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -110,6 +110,10 @@ func resourceKeycloakOpenidClient() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "id": { + Type: schema.TypeString, + Computed: true, + }, "owner_managed_access": { Type: schema.TypeBool, Optional: true, @@ -193,6 +197,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, Name: resourceData["name"].(string), IconUri: resourceData["icon_uri"].(string), OwnerManagedAccess: resourceData["owner_managed_access"].(bool), + Id: resourceData["id"].(string), Uris: uris, Scopes: scopes, Attributes: attributes, @@ -239,7 +244,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien data.Set("access_type", "CONFIDENTIAL") } - resourcesData := make(map[string]interface{}) + resourcesData := []interface{}{} for _, resource := range *resources { resourceData := map[string]interface{}{ @@ -250,10 +255,11 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien "owner_managed_access": resource.OwnerManagedAccess, "scopes": resource.Scopes, "attributes": resource.Attributes, + "id": resource.Id, } - resourcesData[resource.Id] = resourceData + resourcesData = append(resourcesData, resourceData) } - data.Set("resources", resourcesData) + data.Set("resource", resourcesData) } func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interface{}) error { @@ -271,8 +277,8 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - for _, resource := range *resources { - err = keycloakClient.NewOpenidClientResource(client, &resource) + for i := 0; i < len(*resources); i++ { + err = keycloakClient.NewOpenidClientResource(client, &(*resources)[i]) if err != nil { return err } From bcbd78b32720c4b0990057cb2b3a7f500a120fd1 Mon Sep 17 00:00:00 2001 From: Andrew Chubatiuk Date: Fri, 26 Apr 2019 17:25:38 +0300 Subject: [PATCH 05/47] upgraded keycloak and added example --- docker-compose.yml | 2 +- example/main.tf | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6130171c..e8674635 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,7 @@ services: ports: - 8389:389 keycloak: - image: jboss/keycloak:4.8.3.Final + image: jboss/keycloak:6.0.0 depends_on: - postgres - openldap diff --git a/example/main.tf b/example/main.tf index d4f7d298..76958d6a 100644 --- a/example/main.tf +++ b/example/main.tf @@ -89,6 +89,28 @@ resource "keycloak_openid_client" "test_client" { client_secret = "secret" } +resource "keycloak_openid_client" "test_resource_client" { + client_id = "test-openid-client1" + name = "test-openid-client1" + realm_id = "${keycloak_realm.test.id}" + description = "a test openid client" + + access_type = "CONFIDENTIAL" + direct_access_grants_enabled = true + service_accounts_enabled = true + + valid_redirect_uris = [ + "http://localhost:5555/callback", + ] + + resource { + name = "new" + display_name = "new" + } + + client_secret = "secret" +} + resource "keycloak_openid_client_scope" "test_default_client_scope" { name = "test-default-client-scope" realm_id = "${keycloak_realm.test.id}" From 81d574038b82d124ab559ea66fb0882eb85df2ec Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Sun, 28 Apr 2019 01:11:25 +0300 Subject: [PATCH 06/47] minor fix --- provider/keycloak_openid_client.go | 139 ++++++++++++++++++----------- provider/utils.go | 9 ++ 2 files changed, 97 insertions(+), 51 deletions(-) diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index c6205064..7fafa7b7 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -126,7 +126,6 @@ func resourceKeycloakOpenidClient() *schema.Resource { }, "attributes": { Type: schema.TypeMap, - Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, }, @@ -136,7 +135,7 @@ func resourceKeycloakOpenidClient() *schema.Resource { } } -func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResources) { +func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResources, *keycloak.OpenidClientResources, *keycloak.OpenidClientResources) { var validRedirectUris []string var webOrigins []string @@ -168,55 +167,79 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, WebOrigins: webOrigins, } - var resources keycloak.OpenidClientResources + // access type + if accessType := data.Get("access_type").(string); accessType == "PUBLIC" { + openidClient.PublicClient = true + } else if accessType == "BEARER-ONLY" { + openidClient.BearerOnly = true + } + + removeResources := &keycloak.OpenidClientResources{} + unchangedResources := &keycloak.OpenidClientResources{} + addResources := &keycloak.OpenidClientResources{} + unchangedResourcesData := new(schema.Set) if v, ok := data.GetOk("resource"); ok { openidClient.AuthorizationServicesEnabled = true - for _, d := range v.(*schema.Set).List() { - resourceData := d.(map[string]interface{}) - var uris []string - var scopes []string - var attributes map[string][]string - if v, ok := data.GetOk("uris"); ok { - for _, uri := range v.(*schema.Set).List() { - uris = append(uris, uri.(string)) - } - } - if v, ok := data.GetOk("scopes"); ok { - for _, scope := range v.(*schema.Set).List() { - scopes = append(scopes, scope.(string)) - } - } - if v, ok := data.GetOk("attribites"); ok { - for key, value := range v.(map[string]string) { - attributes[key] = strings.Split(value, ",") - } - } - resource := keycloak.OpenidClientResource{ - DisplayName: resourceData["display_name"].(string), - Name: resourceData["name"].(string), - IconUri: resourceData["icon_uri"].(string), - OwnerManagedAccess: resourceData["owner_managed_access"].(bool), - Id: resourceData["id"].(string), - Uris: uris, - Scopes: scopes, - Attributes: attributes, - } - resources = append(resources, resource) - } - + unchangedResourcesData = v.(*schema.Set) } else { openidClient.AuthorizationServicesEnabled = false } - - // access type - if accessType := data.Get("access_type").(string); accessType == "PUBLIC" { - openidClient.PublicClient = true - } else if accessType == "BEARER-ONLY" { - openidClient.BearerOnly = true + if data.HasChange("resource") { + o, n := data.GetChange("resource") + if o == nil { + o = new(schema.Set) + } + if n == nil { + n = new(schema.Set) + } + unchangedResourcesData = unchangedResourcesData.Difference(n.(*schema.Set)) + removeResourcesData := o.(*schema.Set).Difference(n.(*schema.Set)).Difference(unchangedResourcesData).List() + removeResources = getOpenidClientResourcesFromData(removeResourcesData) + addResourcesData := n.(*schema.Set).Difference(o.(*schema.Set)).Difference(unchangedResourcesData).List() + addResources = getOpenidClientResourcesFromData(addResourcesData) } - return openidClient, &resources + unchangedResources = getOpenidClientResourcesFromData(unchangedResourcesData.List()) + + return openidClient, unchangedResources, addResources, removeResources +} + +func getOpenidClientResourcesFromData(data []interface{}) *keycloak.OpenidClientResources { + var resources keycloak.OpenidClientResources + for _, d := range data { + resourceData := d.(map[string]interface{}) + var uris []string + var scopes []string + attributes := map[string][]string{} + if v, ok := resourceData["uris"]; ok { + for _, uri := range v.([]interface{}) { + uris = append(uris, uri.(string)) + } + } + if v, ok := resourceData["scopes"]; ok { + for _, scope := range v.([]interface{}) { + scopes = append(scopes, scope.(string)) + } + } + if v, ok := resourceData["attributes"]; ok { + for key, value := range v.(map[string]interface{}) { + attributes[key] = strings.Split(value.(string), ",") + } + } + resource := keycloak.OpenidClientResource{ + DisplayName: resourceData["display_name"].(string), + Name: resourceData["name"].(string), + IconUri: resourceData["icon_uri"].(string), + OwnerManagedAccess: resourceData["owner_managed_access"].(bool), + Id: resourceData["id"].(string), + Uris: uris, + Scopes: scopes, + Attributes: attributes, + } + resources = append(resources, resource) + } + return &resources } func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, resources *keycloak.OpenidClientResources) { @@ -254,7 +277,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien "icon_uri": resource.IconUri, "owner_managed_access": resource.OwnerManagedAccess, "scopes": resource.Scopes, - "attributes": resource.Attributes, + "attributes": listValueToStr(resource.Attributes), "id": resource.Id, } resourcesData = append(resourcesData, resourceData) @@ -265,7 +288,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client, resources := getOpenidClientFromData(data) + client, _, addResources, _ := getOpenidClientFromData(data) err := keycloakClient.ValidateOpenidClient(client) if err != nil { @@ -277,14 +300,14 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - for i := 0; i < len(*resources); i++ { - err = keycloakClient.NewOpenidClientResource(client, &(*resources)[i]) + for i := 0; i < len(*addResources); i++ { + err = keycloakClient.NewOpenidClientResource(client, &(*addResources)[i]) if err != nil { return err } } - setOpenidClientData(data, client, resources) + setOpenidClientData(data, client, addResources) return resourceKeycloakOpenidClientRead(data, meta) } @@ -313,7 +336,7 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client, resources := getOpenidClientFromData(data) + client, unchangedResources, addResources, removeResources := getOpenidClientFromData(data) err := keycloakClient.ValidateOpenidClient(client) if err != nil { @@ -325,14 +348,28 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac return err } - for _, resource := range *resources { + for _, resource := range *unchangedResources { err = keycloakClient.UpdateOpenidClientResource(client, &resource) if err != nil { return err } } - setOpenidClientData(data, client, resources) + for _, resource := range *addResources { + err = keycloakClient.NewOpenidClientResource(client, &resource) + if err != nil { + return err + } + } + + for _, resource := range *removeResources { + err = keycloakClient.DeleteOpenidClientResource(client.RealmId, client.Id, resource.Id) + if err != nil { + return err + } + } + + setOpenidClientData(data, client, unchangedResources) return nil } diff --git a/provider/utils.go b/provider/utils.go index 657f0b9f..8bc95de6 100644 --- a/provider/utils.go +++ b/provider/utils.go @@ -4,6 +4,7 @@ import ( "github.com/hashicorp/terraform/helper/schema" "github.com/mrparkers/terraform-provider-keycloak/keycloak" "log" + "strings" "time" ) @@ -23,6 +24,14 @@ func mergeSchemas(a map[string]*schema.Schema, b map[string]*schema.Schema) map[ return result } +func listValueToStr(attributes map[string][]string) map[string]interface{} { + output := map[string]interface{}{} + for key, value := range attributes { + output[key] = strings.Join(value, ",") + } + return output +} + // Converts duration string to an int representing the number of seconds, which is used by the Keycloak API // Ex: "1h" => 3600 func getSecondsFromDurationString(s string) (int, error) { From fcce3736c16b236ea92a26f08a1982d1af88325e Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Sun, 28 Apr 2019 11:02:43 +0300 Subject: [PATCH 07/47] fixed resources --- keycloak/openid_client.go | 47 +++++------ provider/keycloak_openid_client.go | 122 +++++++++++++++++------------ 2 files changed, 94 insertions(+), 75 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index db2a1536..f45bacf7 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -23,30 +23,31 @@ type OpenidClientResource struct { type OpenidClientResources []OpenidClientResource +type OpenidClientResourcesDiff struct { + Add OpenidClientResources + Remove OpenidClientResources + Unchanged OpenidClientResources +} + type OpenidClient struct { - Id string `json:"id,omitempty"` - ClientId string `json:"clientId"` - RealmId string `json:"-"` - Name string `json:"name"` - Protocol string `json:"protocol"` // always openid-connect for this resource - ClientAuthenticatorType string `json:"clientAuthenticatorType"` // always client-secret for now, don't have a need for JWT here - ClientSecret string `json:"secret,omitempty"` - - Enabled bool `json:"enabled"` - Description string `json:"description"` - - // Attributes below indicate client access type. If both are false, access type is confidential. Both cannot be true (although the Keycloak API lets you do this) - PublicClient bool `json:"publicClient"` - BearerOnly bool `json:"bearerOnly"` - - StandardFlowEnabled bool `json:"standardFlowEnabled"` - ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` - DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` - ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` - AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` - - ValidRedirectUris []string `json:"redirectUris"` - WebOrigins []string `json:"webOrigins"` + Id string `json:"id,omitempty"` + ClientId string `json:"clientId"` + RealmId string `json:"-"` + Name string `json:"name"` + Protocol string `json:"protocol"` // always openid-connect for this resource + ClientAuthenticatorType string `json:"clientAuthenticatorType"` // always client-secret for now, don't have a need for JWT here + ClientSecret string `json:"secret,omitempty"` + Enabled bool `json:"enabled"` + Description string `json:"description"` + PublicClient bool `json:"publicClient"` + BearerOnly bool `json:"bearerOnly"` + StandardFlowEnabled bool `json:"standardFlowEnabled"` + ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` + DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` + ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` + AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` + ValidRedirectUris []string `json:"redirectUris"` + WebOrigins []string `json:"webOrigins"` } func (keycloakClient *KeycloakClient) NewOpenidClientResource(client *OpenidClient, resource *OpenidClientResource) error { diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 7fafa7b7..1446811e 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -1,6 +1,7 @@ package provider import ( + "errors" "fmt" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" @@ -76,6 +77,11 @@ func resourceKeycloakOpenidClient() *schema.Resource { Optional: true, Default: false, }, + "authorization_services_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, "valid_redirect_uris": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, @@ -135,7 +141,7 @@ func resourceKeycloakOpenidClient() *schema.Resource { } } -func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResources, *keycloak.OpenidClientResources, *keycloak.OpenidClientResources) { +func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResourcesDiff, error) { var validRedirectUris []string var webOrigins []string @@ -152,19 +158,20 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } openidClient := &keycloak.OpenidClient{ - Id: data.Id(), - ClientId: data.Get("client_id").(string), - RealmId: data.Get("realm_id").(string), - Name: data.Get("name").(string), - Enabled: data.Get("enabled").(bool), - Description: data.Get("description").(string), - ClientSecret: data.Get("client_secret").(string), - StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), - ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), - DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), - ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), - ValidRedirectUris: validRedirectUris, - WebOrigins: webOrigins, + Id: data.Id(), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + Name: data.Get("name").(string), + Enabled: data.Get("enabled").(bool), + Description: data.Get("description").(string), + AuthorizationServicesEnabled: data.Get("authorization_services_enabled").(bool), + ClientSecret: data.Get("client_secret").(string), + StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), + ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), + DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), + ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), + ValidRedirectUris: validRedirectUris, + WebOrigins: webOrigins, } // access type @@ -174,16 +181,14 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, openidClient.BearerOnly = true } - removeResources := &keycloak.OpenidClientResources{} - unchangedResources := &keycloak.OpenidClientResources{} - addResources := &keycloak.OpenidClientResources{} - + resources := &keycloak.OpenidClientResourcesDiff{} unchangedResourcesData := new(schema.Set) - if v, ok := data.GetOk("resource"); ok { - openidClient.AuthorizationServicesEnabled = true - unchangedResourcesData = v.(*schema.Set) - } else { - openidClient.AuthorizationServicesEnabled = false + if v, ok := data.GetOk("resource"); ok && data.HasChange("resource") { + if openidClient.AuthorizationServicesEnabled { + unchangedResourcesData = v.(*schema.Set) + } else { + return nil, nil, errors.New("Resources cannot be managed when aunothiztion is not enabled") + } } if data.HasChange("resource") { o, n := data.GetChange("resource") @@ -195,14 +200,14 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } unchangedResourcesData = unchangedResourcesData.Difference(n.(*schema.Set)) removeResourcesData := o.(*schema.Set).Difference(n.(*schema.Set)).Difference(unchangedResourcesData).List() - removeResources = getOpenidClientResourcesFromData(removeResourcesData) + resources.Remove = *getOpenidClientResourcesFromData(removeResourcesData) addResourcesData := n.(*schema.Set).Difference(o.(*schema.Set)).Difference(unchangedResourcesData).List() - addResources = getOpenidClientResourcesFromData(addResourcesData) + resources.Add = *getOpenidClientResourcesFromData(addResourcesData) } - unchangedResources = getOpenidClientResourcesFromData(unchangedResourcesData.List()) + resources.Unchanged = *getOpenidClientResourcesFromData(unchangedResourcesData.List()) - return openidClient, unchangedResources, addResources, removeResources + return openidClient, resources, nil } func getOpenidClientResourcesFromData(data []interface{}) *keycloak.OpenidClientResources { @@ -257,6 +262,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien data.Set("service_accounts_enabled", client.ServiceAccountsEnabled) data.Set("valid_redirect_uris", client.ValidRedirectUris) data.Set("web_origins", client.WebOrigins) + data.Set("authorization_services_enabled", client.AuthorizationServicesEnabled) // access type if client.PublicClient { @@ -288,9 +294,12 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client, _, addResources, _ := getOpenidClientFromData(data) + client, resources, err := getOpenidClientFromData(data) + if err != nil { + return err + } - err := keycloakClient.ValidateOpenidClient(client) + err = keycloakClient.ValidateOpenidClient(client) if err != nil { return err } @@ -300,14 +309,14 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - for i := 0; i < len(*addResources); i++ { - err = keycloakClient.NewOpenidClientResource(client, &(*addResources)[i]) + for i := 0; i < len((*resources).Add); i++ { + err = keycloakClient.NewOpenidClientResource(client, &((*resources).Add)[i]) if err != nil { return err } } - setOpenidClientData(data, client, addResources) + setOpenidClientData(data, client, &resources.Add) return resourceKeycloakOpenidClientRead(data, meta) } @@ -323,9 +332,13 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ return handleNotFoundError(err, data) } - resources, err := keycloakClient.GetOpenidClientResources(realmId, id) - if err != nil { - return handleNotFoundError(err, data) + resources := &keycloak.OpenidClientResources{} + + if client.AuthorizationServicesEnabled { + resources, err = keycloakClient.GetOpenidClientResources(realmId, id) + if err != nil { + return handleNotFoundError(err, data) + } } setOpenidClientData(data, client, resources) @@ -336,9 +349,12 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client, unchangedResources, addResources, removeResources := getOpenidClientFromData(data) + client, resources, err := getOpenidClientFromData(data) + if err != nil { + return err + } - err := keycloakClient.ValidateOpenidClient(client) + err = keycloakClient.ValidateOpenidClient(client) if err != nil { return err } @@ -348,28 +364,30 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac return err } - for _, resource := range *unchangedResources { - err = keycloakClient.UpdateOpenidClientResource(client, &resource) - if err != nil { - return err + if client.AuthorizationServicesEnabled { + for _, resource := range (*resources).Unchanged { + err = keycloakClient.UpdateOpenidClientResource(client, &resource) + if err != nil { + return err + } } - } - for _, resource := range *addResources { - err = keycloakClient.NewOpenidClientResource(client, &resource) - if err != nil { - return err + for _, resource := range (*resources).Add { + err = keycloakClient.NewOpenidClientResource(client, &resource) + if err != nil { + return err + } } - } - for _, resource := range *removeResources { - err = keycloakClient.DeleteOpenidClientResource(client.RealmId, client.Id, resource.Id) - if err != nil { - return err + for _, resource := range (*resources).Remove { + err = keycloakClient.DeleteOpenidClientResource(client.RealmId, client.Id, resource.Id) + if err != nil { + return err + } } } - setOpenidClientData(data, client, unchangedResources) + setOpenidClientData(data, client, &resources.Unchanged) return nil } From 1e4144561f0d04baa0aa40f28673767cdfc896fe Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Sun, 28 Apr 2019 11:22:11 +0300 Subject: [PATCH 08/47] fixed web origins --- provider/keycloak_openid_client.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 1446811e..b637dd6e 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -142,8 +142,8 @@ func resourceKeycloakOpenidClient() *schema.Resource { } func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResourcesDiff, error) { - var validRedirectUris []string - var webOrigins []string + validRedirectUris := make([]string, 0) + webOrigins := make([]string, 0) if v, ok := data.GetOk("valid_redirect_uris"); ok { for _, validRedirectUri := range v.(*schema.Set).List() { @@ -174,6 +174,18 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, WebOrigins: webOrigins, } + if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled { + if _, ok := data.GetOk("valid_redirect_uris"); ok { + return nil, nil, errors.New("valid_redirect_uris cannot be set when standard or implicit flow is not enabled") + } + } + + if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled && !openidClient.DirectAccessGrantsEnabled { + if _, ok := data.GetOk("web_origins"); ok { + return nil, nil, errors.New("web_origins cannot be set when standard or implicit flow is not enabled") + } + } + // access type if accessType := data.Get("access_type").(string); accessType == "PUBLIC" { openidClient.PublicClient = true From 2c1c57b6a326dd365e8bb59df15556534d0de370 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Mon, 29 Apr 2019 23:35:00 +0300 Subject: [PATCH 09/47] added openid client authorization resources --- keycloak/custom_user_federation.go | 4 +- keycloak/generic_client.go | 2 +- keycloak/group.go | 8 +- keycloak/identity_provider.go | 4 +- keycloak/identity_provider_mapper.go | 4 +- keycloak/keycloak_client.go | 25 +- keycloak/ldap_full_name_mapper.go | 4 +- keycloak/ldap_group_mapper.go | 4 +- .../ldap_msad_user_account_control_mapper.go | 4 +- keycloak/ldap_user_attribute_mapper.go | 4 +- keycloak/ldap_user_federation.go | 4 +- keycloak/openid_audience_protocol_mapper.go | 4 +- keycloak/openid_client.go | 333 +++++++++++++++--- keycloak/openid_client_scope.go | 6 +- keycloak/openid_full_name_protocol_mapper.go | 4 +- ...openid_group_membership_protocol_mapper.go | 4 +- .../openid_hardcoded_claim_protocol_mapper.go | 4 +- .../openid_user_attribute_protocol_mapper.go | 4 +- .../openid_user_property_protocol_mapper.go | 4 +- keycloak/protocol_mapper.go | 2 +- keycloak/realm.go | 6 +- keycloak/saml_client.go | 4 +- .../saml_user_attribute_protocol_mapper.go | 4 +- .../saml_user_property_protocol_mapper.go | 4 +- keycloak/server_info.go | 2 +- keycloak/user.go | 28 +- .../data_source_keycloak_openid_client.go | 105 ++++++ ...loak_openid_client_authorization_policy.go | 90 +++++ provider/keycloak_openid_client.go | 241 +++---------- ..._openid_client_authorization_permission.go | 177 ++++++++++ ...ak_openid_client_authorization_resource.go | 192 ++++++++++ ...cloak_openid_client_authorization_scope.go | 135 +++++++ ...loak_openid_client_service_account_role.go | 113 ++++++ provider/keycloak_user.go | 67 +++- provider/provider.go | 8 + 35 files changed, 1304 insertions(+), 304 deletions(-) create mode 100644 provider/data_source_keycloak_openid_client.go create mode 100644 provider/data_source_keycloak_openid_client_authorization_policy.go create mode 100644 provider/keycloak_openid_client_authorization_permission.go create mode 100644 provider/keycloak_openid_client_authorization_resource.go create mode 100644 provider/keycloak_openid_client_authorization_scope.go create mode 100644 provider/keycloak_openid_client_service_account_role.go diff --git a/keycloak/custom_user_federation.go b/keycloak/custom_user_federation.go index 313115e6..9ebf1e40 100644 --- a/keycloak/custom_user_federation.go +++ b/keycloak/custom_user_federation.go @@ -98,7 +98,7 @@ func (keycloakClient *KeycloakClient) NewCustomUserFederation(customUserFederati func (keycloakClient *KeycloakClient) GetCustomUserFederation(realmId, id string) (*CustomUserFederation, error) { var component *component - err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil) if err != nil { return nil, err } @@ -111,5 +111,5 @@ func (keycloakClient *KeycloakClient) UpdateCustomUserFederation(customUserFeder } func (keycloakClient *KeycloakClient) DeleteCustomUserFederation(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil) } diff --git a/keycloak/generic_client.go b/keycloak/generic_client.go index 5f97220b..6c98ac64 100644 --- a/keycloak/generic_client.go +++ b/keycloak/generic_client.go @@ -16,7 +16,7 @@ type GenericClient struct { func (keycloakClient *KeycloakClient) listGenericClients(realmId string) ([]*GenericClient, error) { var clients []*GenericClient - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients", realmId), &clients) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients", realmId), &clients, nil) if err != nil { return nil, err } diff --git a/keycloak/group.go b/keycloak/group.go index 0a98b7fa..7766f02d 100644 --- a/keycloak/group.go +++ b/keycloak/group.go @@ -92,7 +92,7 @@ func (keycloakClient *KeycloakClient) NewGroup(group *Group) error { func (keycloakClient *KeycloakClient) GetGroup(realmId, id string) (*Group, error) { var group Group - err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups/%s", realmId, id), &group) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups/%s", realmId, id), &group, nil) if err != nil { return nil, err } @@ -114,13 +114,13 @@ func (keycloakClient *KeycloakClient) UpdateGroup(group *Group) error { } func (keycloakClient *KeycloakClient) DeleteGroup(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/groups/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/groups/%s", realmId, id), nil) } func (keycloakClient *KeycloakClient) ListGroupsWithName(realmId, name string) ([]*Group, error) { var groups []*Group - err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups?search=%s", realmId, url.QueryEscape(name)), &groups) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups?search=%s", realmId, url.QueryEscape(name)), &groups, nil) if err != nil { return nil, err } @@ -131,7 +131,7 @@ func (keycloakClient *KeycloakClient) ListGroupsWithName(realmId, name string) ( func (keycloakClient *KeycloakClient) GetGroupMembers(realmId, groupId string) ([]*User, error) { var users []*User - err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups/%s/members", realmId, groupId), &users) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups/%s/members", realmId, groupId), &users, nil) if err != nil { return nil, err } diff --git a/keycloak/identity_provider.go b/keycloak/identity_provider.go index b01a1af6..32de6a54 100644 --- a/keycloak/identity_provider.go +++ b/keycloak/identity_provider.go @@ -65,7 +65,7 @@ func (keycloakClient *KeycloakClient) GetIdentityProvider(realm, alias string) ( var identityProvider IdentityProvider identityProvider.Realm = realm - err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias), &identityProvider) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias), &identityProvider, nil) if err != nil { return nil, err } @@ -78,5 +78,5 @@ func (keycloakClient *KeycloakClient) UpdateIdentityProvider(identityProvider *I } func (keycloakClient *KeycloakClient) DeleteIdentityProvider(realm, alias string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s", realm, alias), nil) } diff --git a/keycloak/identity_provider_mapper.go b/keycloak/identity_provider_mapper.go index 8151850e..f30927a6 100644 --- a/keycloak/identity_provider_mapper.go +++ b/keycloak/identity_provider_mapper.go @@ -44,7 +44,7 @@ func (keycloakClient *KeycloakClient) GetIdentityProviderMapper(realm, alias, id identityProviderMapper.Realm = realm identityProviderMapper.IdentityProviderAlias = alias - err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", realm, alias, id), &identityProviderMapper) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", realm, alias, id), &identityProviderMapper, nil) if err != nil { return nil, err } @@ -57,5 +57,5 @@ func (keycloakClient *KeycloakClient) UpdateIdentityProviderMapper(identityProvi } func (keycloakClient *KeycloakClient) DeleteIdentityProviderMapper(realm, alias, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", realm, alias, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/identity-provider/instances/%s/mappers/%s", realm, alias, id), nil) } diff --git a/keycloak/keycloak_client.go b/keycloak/keycloak_client.go index b254f296..41f22016 100644 --- a/keycloak/keycloak_client.go +++ b/keycloak/keycloak_client.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "io" "io/ioutil" "log" "net/http" @@ -247,7 +248,7 @@ func (keycloakClient *KeycloakClient) sendRequest(request *http.Request) ([]byte return body, response.Header.Get("Location"), nil } -func (keycloakClient *KeycloakClient) get(path string, resource interface{}) error { +func (keycloakClient *KeycloakClient) get(path string, resource interface{}, params map[string]string) error { resourceUrl := keycloakClient.baseUrl + apiUrl + path request, err := http.NewRequest(http.MethodGet, resourceUrl, nil) @@ -255,6 +256,14 @@ func (keycloakClient *KeycloakClient) get(path string, resource interface{}) err return err } + if params != nil { + query := url.Values{} + for k, v := range params { + query.Add(k, v) + } + request.URL.RawQuery = query.Encode() + } + body, _, err := keycloakClient.sendRequest(request) if err != nil { return err @@ -299,10 +308,20 @@ func (keycloakClient *KeycloakClient) put(path string, requestBody interface{}) return err } -func (keycloakClient *KeycloakClient) delete(path string) error { +func (keycloakClient *KeycloakClient) delete(path string, requestBody interface{}) error { resourceUrl := keycloakClient.baseUrl + apiUrl + path - request, err := http.NewRequest(http.MethodDelete, resourceUrl, nil) + var body io.Reader + + if requestBody != nil { + payload, err := json.Marshal(requestBody) + if err != nil { + return err + } + body = bytes.NewReader(payload) + } + + request, err := http.NewRequest(http.MethodDelete, resourceUrl, body) if err != nil { return err } diff --git a/keycloak/ldap_full_name_mapper.go b/keycloak/ldap_full_name_mapper.go index 9b9c5907..bcf677ce 100644 --- a/keycloak/ldap_full_name_mapper.go +++ b/keycloak/ldap_full_name_mapper.go @@ -95,7 +95,7 @@ func (keycloakClient *KeycloakClient) NewLdapFullNameMapper(ldapFullNameMapper * func (keycloakClient *KeycloakClient) GetLdapFullNameMapper(realmId, id string) (*LdapFullNameMapper, error) { var component *component - err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil) if err != nil { return nil, err } @@ -108,5 +108,5 @@ func (keycloakClient *KeycloakClient) UpdateLdapFullNameMapper(ldapFullNameMappe } func (keycloakClient *KeycloakClient) DeleteLdapFullNameMapper(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil) } diff --git a/keycloak/ldap_group_mapper.go b/keycloak/ldap_group_mapper.go index c55a226a..cc7d460d 100644 --- a/keycloak/ldap_group_mapper.go +++ b/keycloak/ldap_group_mapper.go @@ -166,7 +166,7 @@ func (keycloakClient *KeycloakClient) NewLdapGroupMapper(ldapGroupMapper *LdapGr func (keycloakClient *KeycloakClient) GetLdapGroupMapper(realmId, id string) (*LdapGroupMapper, error) { var component *component - err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil) if err != nil { return nil, err } @@ -179,5 +179,5 @@ func (keycloakClient *KeycloakClient) UpdateLdapGroupMapper(ldapGroupMapper *Lda } func (keycloakClient *KeycloakClient) DeleteLdapGroupMapper(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil) } diff --git a/keycloak/ldap_msad_user_account_control_mapper.go b/keycloak/ldap_msad_user_account_control_mapper.go index 45b2e816..a2890bb7 100644 --- a/keycloak/ldap_msad_user_account_control_mapper.go +++ b/keycloak/ldap_msad_user_account_control_mapper.go @@ -59,7 +59,7 @@ func (keycloakClient *KeycloakClient) NewLdapMsadUserAccountControlMapper(ldapMs func (keycloakClient *KeycloakClient) GetLdapMsadUserAccountControlMapper(realmId, id string) (*LdapMsadUserAccountControlMapper, error) { var component *component - err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil) if err != nil { return nil, err } @@ -72,5 +72,5 @@ func (keycloakClient *KeycloakClient) UpdateLdapMsadUserAccountControlMapper(lda } func (keycloakClient *KeycloakClient) DeleteLdapMsadUserAccountControlMapper(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil) } diff --git a/keycloak/ldap_user_attribute_mapper.go b/keycloak/ldap_user_attribute_mapper.go index 75ff1548..3b164bcb 100644 --- a/keycloak/ldap_user_attribute_mapper.go +++ b/keycloak/ldap_user_attribute_mapper.go @@ -89,7 +89,7 @@ func (keycloakClient *KeycloakClient) NewLdapUserAttributeMapper(ldapUserAttribu func (keycloakClient *KeycloakClient) GetLdapUserAttributeMapper(realmId, id string) (*LdapUserAttributeMapper, error) { var component *component - err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil) if err != nil { return nil, err } @@ -102,5 +102,5 @@ func (keycloakClient *KeycloakClient) UpdateLdapUserAttributeMapper(ldapUserAttr } func (keycloakClient *KeycloakClient) DeleteLdapUserAttributeMapper(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil) } diff --git a/keycloak/ldap_user_federation.go b/keycloak/ldap_user_federation.go index 9a00d3b1..ea1b3d05 100644 --- a/keycloak/ldap_user_federation.go +++ b/keycloak/ldap_user_federation.go @@ -316,7 +316,7 @@ func (keycloakClient *KeycloakClient) NewLdapUserFederation(ldapUserFederation * func (keycloakClient *KeycloakClient) GetLdapUserFederation(realmId, id string) (*LdapUserFederation, error) { var component *component - err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil) if err != nil { return nil, err } @@ -334,5 +334,5 @@ func (keycloakClient *KeycloakClient) UpdateLdapUserFederation(ldapUserFederatio } func (keycloakClient *KeycloakClient) DeleteLdapUserFederation(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil) } diff --git a/keycloak/openid_audience_protocol_mapper.go b/keycloak/openid_audience_protocol_mapper.go index 6d8ed4a9..3e204e57 100644 --- a/keycloak/openid_audience_protocol_mapper.go +++ b/keycloak/openid_audience_protocol_mapper.go @@ -63,7 +63,7 @@ func (protocolMapper *protocolMapper) convertToOpenIdAudienceProtocolMapper(real func (keycloakClient *KeycloakClient) GetOpenIdAudienceProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*OpenIdAudienceProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -72,7 +72,7 @@ func (keycloakClient *KeycloakClient) GetOpenIdAudienceProtocolMapper(realmId, c } func (keycloakClient *KeycloakClient) DeleteOpenIdAudienceProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewOpenIdAudienceProtocolMapper(mapper *OpenIdAudienceProtocolMapper) error { diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index f45bacf7..c319ba80 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -5,53 +5,237 @@ import ( "fmt" ) +type OpenidClientRole struct { + Id string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + ScopeParamRequired bool `json:"scopeParamRequired"` + ClientRole bool `json:"clientRole"` + ContainerId string `json:"ContainerId"` +} + type OpenidClientSecret struct { Type string `json:"type"` Value string `json:"value"` } -type OpenidClientResource struct { - Id string `json:"_id,omitempty"` - DisplayName string `json:"displayName"` - Name string `json:"name"` - Uris []string `json:"uris"` - IconUri string `json:"icon_uri"` - OwnerManagedAccess bool `json:"ownerManagedAccess"` - Scopes []string `json:"scopes"` - Attributes map[string][]string `json:"attributes"` +type OpenidClientAuthorizationResource struct { + ClientId string `json:"-"` + RealmId string `json:"-"` + Id string `json:"_id,omitempty"` + DisplayName string `json:"displayName"` + Name string `json:"name"` + Uris []string `json:"uris"` + IconUri string `json:"icon_uri"` + OwnerManagedAccess bool `json:"ownerManagedAccess"` + Scopes []OpenidClientAuthorizationScope `json:"scopes"` + Type string `json:"type"` + Attributes map[string][]string `json:"attributes"` +} + +type OpenidClientAuthorizationScope struct { + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ClientId string `json:"-"` + Name string `json:"name"` + DisplayName string `json:"displayName"` + IconUri string `json:"iconUri"` } -type OpenidClientResources []OpenidClientResource +type OpenidClientAuthorizationPermission struct { + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ClientId string `json:"-"` + Name string `json:"name"` + Description string `json:"description"` + DecisionStrategy string `json:"decisionStrategy"` + Policies []string `json:"policies"` + Resources []string `json:"resources"` + Type string `json:"type"` +} + +type OpenidClientAuthorizationPolicy struct { + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ClientId string `json:"-"` + Name string `json:"name"` + Owner string `json:"owner"` + DecisionStrategy string `json:"decisionStrategy"` + Logic string `json:"logic"` + Policies []string `json:"policies"` + Resources []string `json:"resources"` + Scopes []string `json:"scopes"` + Type string `json:"type"` +} -type OpenidClientResourcesDiff struct { - Add OpenidClientResources - Remove OpenidClientResources - Unchanged OpenidClientResources +type OpenidClientServiceAccountRole struct { + Id string `json:"id"` + RealmId string `json:"-"` + ClientId string `json:"-"` + Name string `json:"name"` + ClientRole bool `json:"clientRole"` + Composite bool `json:"composite"` + ContainerId string `json:"containerId"` +} + +type OpenidClientAuthorizationSettings struct { + PolicyEnforcementMode string `json:"policyEnforcementMode,omitempty"` + AllowRemoteResourceManagement bool `json:"allowRemoteResourceManagement,omitempty"` } type OpenidClient struct { - Id string `json:"id,omitempty"` - ClientId string `json:"clientId"` - RealmId string `json:"-"` - Name string `json:"name"` - Protocol string `json:"protocol"` // always openid-connect for this resource - ClientAuthenticatorType string `json:"clientAuthenticatorType"` // always client-secret for now, don't have a need for JWT here - ClientSecret string `json:"secret,omitempty"` - Enabled bool `json:"enabled"` - Description string `json:"description"` - PublicClient bool `json:"publicClient"` - BearerOnly bool `json:"bearerOnly"` - StandardFlowEnabled bool `json:"standardFlowEnabled"` - ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` - DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` - ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` - AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` - ValidRedirectUris []string `json:"redirectUris"` - WebOrigins []string `json:"webOrigins"` -} - -func (keycloakClient *KeycloakClient) NewOpenidClientResource(client *OpenidClient, resource *OpenidClientResource) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", client.RealmId, client.Id), resource) + Id string `json:"id,omitempty"` + ClientId string `json:"clientId"` + RealmId string `json:"-"` + Name string `json:"name"` + Protocol string `json:"protocol"` // always openid-connect for this resource + ClientAuthenticatorType string `json:"clientAuthenticatorType"` // always client-secret for now, don't have a need for JWT here + ClientSecret string `json:"secret,omitempty"` + Enabled bool `json:"enabled"` + Description string `json:"description"` + PublicClient bool `json:"publicClient"` + BearerOnly bool `json:"bearerOnly"` + StandardFlowEnabled bool `json:"standardFlowEnabled"` + ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` + DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` + ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` + AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` + ValidRedirectUris []string `json:"redirectUris,omitempty"` + WebOrigins []string `json:"webOrigins,omitempty"` + AuthorizationSettings OpenidClientAuthorizationSettings `json:"authorizationSettings,omitempty"` +} + +func (keycloakClient *KeycloakClient) GetClientAuthorizationPolicyByName(realmId, clientId, name string) (*OpenidClientAuthorizationPolicy, error) { + policies := []OpenidClientAuthorizationPolicy{} + params := map[string]string{"name": name} + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy", realmId, clientId), &policies, params) + if err != nil { + return nil, err + } + policy := policies[0] + policy.RealmId = realmId + policy.ClientId = clientId + policy.Name = name + return &policy, nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(realm, clientId, id string) (*OpenidClientAuthorizationPermission, error) { + permission := OpenidClientAuthorizationPermission{ + RealmId: realm, + ClientId: clientId, + Id: id, + } + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, clientId, id), &permission, nil) + if err != nil { + return nil, err + } + return &permission, nil +} + +func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource", permission.RealmId, permission.ClientId), permission) + if err != nil { + return err + } + err = json.Unmarshal(body, &permission) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ClientId, permission.Id), permission) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationPermission(realmId, clientId, permissionId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realmId, clientId, permissionId), nil) +} + +func (keycloakClient *KeycloakClient) GetClientRoleByName(realm, clientId, name string) (*OpenidClientRole, error) { + var clientRole OpenidClientRole + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/roles/%s", realm, clientId, name), &clientRole, nil) + if err != nil { + return nil, err + } + return &clientRole, nil +} + +func (keycloakClient *KeycloakClient) GetClientByName(realm, clientId string) (*OpenidClient, error) { + var clients []OpenidClient + params := map[string]string{"clientId": clientId} + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients", realm), &clients, params) + if err != nil { + return nil, err + } + return &clients[0], nil +} + +func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceAccountRole *OpenidClientServiceAccountRole) error { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(serviceAccountRole.RealmId, serviceAccountRole.ClientId) + if err != nil { + return err + } + role, err := keycloakClient.GetClientRoleByName(serviceAccountRole.RealmId, serviceAccountRole.ContainerId, serviceAccountRole.Name) + if err != nil { + return err + } + serviceAccountRole.Id = role.Id + serviceAccountRoles := []OpenidClientServiceAccountRole{} + serviceAccountRoles = append(serviceAccountRoles, *serviceAccountRole) + _, _, err = keycloakClient.post(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", serviceAccountRole.RealmId, serviceAccountUser.Id, serviceAccountRole.ContainerId), serviceAccountRoles) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, sourceClientId, targetClientId, roleId string) error { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(realm, targetClientId) + if err != nil { + return err + } + serviceAccountRoles := []OpenidClientServiceAccountRole{} + serviceAccountRoles = append(serviceAccountRoles, OpenidClientServiceAccountRole{ + Id: roleId, + }) + err = keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUser.Id, sourceClientId), &serviceAccountRoles) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, sourceClientId, targetClientId, roleId string) (*OpenidClientServiceAccountRole, error) { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(realm, targetClientId) + if err != nil { + return nil, err + } + serviceAccountRoles := []OpenidClientServiceAccountRole{} + serviceAccountRoles = append(serviceAccountRoles, OpenidClientServiceAccountRole{ + Id: roleId, + RealmId: realm, + ContainerId: sourceClientId, + ClientId: targetClientId, + }) + err = keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUser.Id, sourceClientId), &serviceAccountRoles, nil) + if err != nil { + return nil, err + } + for _, serviceAccountRole := range serviceAccountRoles { + if serviceAccountRole.Id == roleId { + return &serviceAccountRole, nil + } + } + return nil, fmt.Errorf("No role with id %s found", roleId) +} + +func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", resource.RealmId, resource.ClientId), resource) if err != nil { return err } @@ -62,34 +246,73 @@ func (keycloakClient *KeycloakClient) NewOpenidClientResource(client *OpenidClie return nil } -func (keycloakClient *KeycloakClient) GetOpenidClientResource(realm string, clientId string, resourceId string) (*OpenidClientResource, error) { - var clientResource OpenidClientResource - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, clientId, resourceId), &clientResource) +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm, clientId, resourceId string) (*OpenidClientAuthorizationResource, error) { + resource := OpenidClientAuthorizationResource{ + RealmId: realm, + ClientId: clientId, + } + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, clientId, resourceId), &resource, nil) if err != nil { return nil, err } - return &clientResource, nil + return &resource, nil +} + +func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", resource.RealmId, resource.ClientId, resource.Id), resource) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationResource(realmId, clientId, resourceId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realmId, clientId, resourceId), nil) +} + +func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope", scope.RealmId, scope.ClientId), scope) + if err != nil { + return err + } + err = json.Unmarshal(body, &scope) + if err != nil { + return err + } + return nil } -func (keycloakClient *KeycloakClient) GetOpenidClientResources(realm string, clientId string) (*OpenidClientResources, error) { - var clientResources *OpenidClientResources - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", realm, clientId), &clientResources) +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationScope(realm, clientId, scopeId string) (*OpenidClientAuthorizationScope, error) { + scope := OpenidClientAuthorizationScope{ + RealmId: realm, + ClientId: clientId, + } + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realm, clientId, scopeId), &scope, nil) if err != nil { return nil, err } - return clientResources, nil + return &scope, nil } -func (keycloakClient *KeycloakClient) UpdateOpenidClientResource(client *OpenidClient, resource *OpenidClientResource) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", client.RealmId, client.Id, resource.Id), resource) +func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", scope.RealmId, scope.ClientId, scope.Id), scope) if err != nil { return err } return nil } -func (keycloakClient *KeycloakClient) DeleteOpenidClientResource(realmId, clientId string, resourceId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realmId, clientId, resourceId)) +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationScope(realmId, clientId, scopeId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realmId, clientId, scopeId), nil) +} + +func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountUserId(realmId, clientId string) (*User, error) { + var serviceAccountUser User + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/service-account-user", realmId, clientId), &serviceAccountUser, nil) + if err != nil { + return &serviceAccountUser, err + } + return &serviceAccountUser, nil } func (keycloakClient *KeycloakClient) ValidateOpenidClient(client *OpenidClient) error { @@ -126,12 +349,12 @@ func (keycloakClient *KeycloakClient) GetOpenidClient(realmId, id string) (*Open var client OpenidClient var clientSecret OpenidClientSecret - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), &client) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), &client, nil) if err != nil { return nil, err } - err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/client-secret", realmId, id), &clientSecret) + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/client-secret", realmId, id), &clientSecret, nil) if err != nil { return nil, err } @@ -146,7 +369,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientByClientId(realmId, clientI var clients []OpenidClient var clientSecret OpenidClientSecret - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients?clientId=%s", realmId, clientId), &clients) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients?clientId=%s", realmId, clientId), &clients, nil) if err != nil { return nil, err } @@ -157,7 +380,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientByClientId(realmId, clientI client := clients[0] - err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/client-secret", realmId, client.Id), &clientSecret) + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/client-secret", realmId, client.Id), &clientSecret, nil) if err != nil { return nil, err } @@ -176,13 +399,13 @@ func (keycloakClient *KeycloakClient) UpdateOpenidClient(client *OpenidClient) e } func (keycloakClient *KeycloakClient) DeleteOpenidClient(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), nil) } func (keycloakClient *KeycloakClient) getOpenidClientScopes(realmId, clientId, t string) ([]*OpenidClientScope, error) { var scopes []*OpenidClientScope - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/%s-client-scopes", realmId, clientId, t), &scopes) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/%s-client-scopes", realmId, clientId, t), &scopes, nil) if err != nil { return nil, err } @@ -265,7 +488,7 @@ func (keycloakClient *KeycloakClient) detachOpenidClientScopes(realmId, clientId } for _, openidClientScope := range allOpenidClientScopes { - err := keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/%s-client-scopes/%s", realmId, clientId, t, openidClientScope.Id)) + err := keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/%s-client-scopes/%s", realmId, clientId, t, openidClientScope.Id), nil) if err != nil { return err } diff --git a/keycloak/openid_client_scope.go b/keycloak/openid_client_scope.go index 9c76d083..c21aba49 100644 --- a/keycloak/openid_client_scope.go +++ b/keycloak/openid_client_scope.go @@ -34,7 +34,7 @@ func (keycloakClient *KeycloakClient) NewOpenidClientScope(clientScope *OpenidCl func (keycloakClient *KeycloakClient) GetOpenidClientScope(realmId, id string) (*OpenidClientScope, error) { var clientScope OpenidClientScope - err := keycloakClient.get(fmt.Sprintf("/realms/%s/client-scopes/%s", realmId, id), &clientScope) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/client-scopes/%s", realmId, id), &clientScope, nil) if err != nil { return nil, err } @@ -51,14 +51,14 @@ func (keycloakClient *KeycloakClient) UpdateOpenidClientScope(clientScope *Openi } func (keycloakClient *KeycloakClient) DeleteOpenidClientScope(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/client-scopes/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/client-scopes/%s", realmId, id), nil) } func (keycloakClient *KeycloakClient) listOpenidClientScopesWithFilter(realmId string, filter OpenidClientScopeFilterFunc) ([]*OpenidClientScope, error) { var clientScopes []OpenidClientScope var openidClientScopes []*OpenidClientScope - err := keycloakClient.get(fmt.Sprintf("/realms/%s/client-scopes", realmId), &clientScopes) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/client-scopes", realmId), &clientScopes, nil) if err != nil { return nil, err } diff --git a/keycloak/openid_full_name_protocol_mapper.go b/keycloak/openid_full_name_protocol_mapper.go index e78c5f8f..a77b82ae 100644 --- a/keycloak/openid_full_name_protocol_mapper.go +++ b/keycloak/openid_full_name_protocol_mapper.go @@ -63,7 +63,7 @@ func (protocolMapper *protocolMapper) convertToOpenIdFullNameProtocolMapper(real func (keycloakClient *KeycloakClient) GetOpenIdFullNameProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*OpenIdFullNameProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -72,7 +72,7 @@ func (keycloakClient *KeycloakClient) GetOpenIdFullNameProtocolMapper(realmId, c } func (keycloakClient *KeycloakClient) DeleteOpenIdFullNameProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewOpenIdFullNameProtocolMapper(mapper *OpenIdFullNameProtocolMapper) error { diff --git a/keycloak/openid_group_membership_protocol_mapper.go b/keycloak/openid_group_membership_protocol_mapper.go index 1fc5c0ac..256c2977 100644 --- a/keycloak/openid_group_membership_protocol_mapper.go +++ b/keycloak/openid_group_membership_protocol_mapper.go @@ -75,7 +75,7 @@ func (protocolMapper *protocolMapper) convertToOpenIdGroupMembershipProtocolMapp func (keycloakClient *KeycloakClient) GetOpenIdGroupMembershipProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*OpenIdGroupMembershipProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (keycloakClient *KeycloakClient) GetOpenIdGroupMembershipProtocolMapper(rea } func (keycloakClient *KeycloakClient) DeleteOpenIdGroupMembershipProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewOpenIdGroupMembershipProtocolMapper(mapper *OpenIdGroupMembershipProtocolMapper) error { diff --git a/keycloak/openid_hardcoded_claim_protocol_mapper.go b/keycloak/openid_hardcoded_claim_protocol_mapper.go index 0fe50d69..7a921a1c 100644 --- a/keycloak/openid_hardcoded_claim_protocol_mapper.go +++ b/keycloak/openid_hardcoded_claim_protocol_mapper.go @@ -74,7 +74,7 @@ func (protocolMapper *protocolMapper) convertToOpenIdHardcodedClaimProtocolMappe func (keycloakClient *KeycloakClient) GetOpenIdHardcodedClaimProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*OpenIdHardcodedClaimProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -83,7 +83,7 @@ func (keycloakClient *KeycloakClient) GetOpenIdHardcodedClaimProtocolMapper(real } func (keycloakClient *KeycloakClient) DeleteOpenIdHardcodedClaimProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewOpenIdHardcodedClaimProtocolMapper(mapper *OpenIdHardcodedClaimProtocolMapper) error { diff --git a/keycloak/openid_user_attribute_protocol_mapper.go b/keycloak/openid_user_attribute_protocol_mapper.go index a91e591d..ea9faf3a 100644 --- a/keycloak/openid_user_attribute_protocol_mapper.go +++ b/keycloak/openid_user_attribute_protocol_mapper.go @@ -84,7 +84,7 @@ func (protocolMapper *protocolMapper) convertToOpenIdUserAttributeProtocolMapper func (keycloakClient *KeycloakClient) GetOpenIdUserAttributeProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*OpenIdUserAttributeProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -93,7 +93,7 @@ func (keycloakClient *KeycloakClient) GetOpenIdUserAttributeProtocolMapper(realm } func (keycloakClient *KeycloakClient) DeleteOpenIdUserAttributeProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewOpenIdUserAttributeProtocolMapper(mapper *OpenIdUserAttributeProtocolMapper) error { diff --git a/keycloak/openid_user_property_protocol_mapper.go b/keycloak/openid_user_property_protocol_mapper.go index c436b761..9595bced 100644 --- a/keycloak/openid_user_property_protocol_mapper.go +++ b/keycloak/openid_user_property_protocol_mapper.go @@ -74,7 +74,7 @@ func (protocolMapper *protocolMapper) convertToOpenIdUserPropertyProtocolMapper( func (keycloakClient *KeycloakClient) GetOpenIdUserPropertyProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*OpenIdUserPropertyProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -83,7 +83,7 @@ func (keycloakClient *KeycloakClient) GetOpenIdUserPropertyProtocolMapper(realmI } func (keycloakClient *KeycloakClient) DeleteOpenIdUserPropertyProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewOpenIdUserPropertyProtocolMapper(mapper *OpenIdUserPropertyProtocolMapper) error { diff --git a/keycloak/protocol_mapper.go b/keycloak/protocol_mapper.go index 51465472..92693e1c 100644 --- a/keycloak/protocol_mapper.go +++ b/keycloak/protocol_mapper.go @@ -48,7 +48,7 @@ func individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId str func (keycloakClient *KeycloakClient) listGenericProtocolMappers(realmId, clientId, clientScopeId string) ([]*protocolMapper, error) { var protocolMappers []*protocolMapper - err := keycloakClient.get(protocolMapperPath(realmId, clientId, clientScopeId), &protocolMappers) + err := keycloakClient.get(protocolMapperPath(realmId, clientId, clientScopeId), &protocolMappers, nil) if err != nil { return nil, err } diff --git a/keycloak/realm.go b/keycloak/realm.go index cbb5426d..d45a2f62 100644 --- a/keycloak/realm.go +++ b/keycloak/realm.go @@ -51,7 +51,7 @@ func (keycloakClient *KeycloakClient) NewRealm(realm *Realm) error { func (keycloakClient *KeycloakClient) GetRealm(id string) (*Realm, error) { var realm Realm - err := keycloakClient.get(fmt.Sprintf("/realms/%s", id), &realm) + err := keycloakClient.get(fmt.Sprintf("/realms/%s", id), &realm, nil) if err != nil { return nil, err } @@ -64,10 +64,10 @@ func (keycloakClient *KeycloakClient) UpdateRealm(realm *Realm) error { } func (keycloakClient *KeycloakClient) DeleteRealm(id string) error { - err := keycloakClient.delete(fmt.Sprintf("/realms/%s", id)) + err := keycloakClient.delete(fmt.Sprintf("/realms/%s", id), nil) if err != nil { // For whatever reason, this fails sometimes with a 500 during acceptance tests. try again - return keycloakClient.delete(fmt.Sprintf("/realms/%s", id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s", id), nil) } return nil diff --git a/keycloak/saml_client.go b/keycloak/saml_client.go index 002cb0e3..7350bb01 100644 --- a/keycloak/saml_client.go +++ b/keycloak/saml_client.go @@ -60,7 +60,7 @@ func (keycloakClient *KeycloakClient) NewSamlClient(client *SamlClient) error { func (keycloakClient *KeycloakClient) GetSamlClient(realmId, id string) (*SamlClient, error) { var client SamlClient - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), &client) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), &client, nil) if err != nil { return nil, err } @@ -78,5 +78,5 @@ func (keycloakClient *KeycloakClient) UpdateSamlClient(client *SamlClient) error } func (keycloakClient *KeycloakClient) DeleteSamlClient(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s", realmId, id), nil) } diff --git a/keycloak/saml_user_attribute_protocol_mapper.go b/keycloak/saml_user_attribute_protocol_mapper.go index 979ff770..5c760fdd 100644 --- a/keycloak/saml_user_attribute_protocol_mapper.go +++ b/keycloak/saml_user_attribute_protocol_mapper.go @@ -50,7 +50,7 @@ func (protocolMapper *protocolMapper) convertToSamlUserAttributeProtocolMapper(r func (keycloakClient *KeycloakClient) GetSamlUserAttributeProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*SamlUserAttributeProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -59,7 +59,7 @@ func (keycloakClient *KeycloakClient) GetSamlUserAttributeProtocolMapper(realmId } func (keycloakClient *KeycloakClient) DeleteSamlUserAttributeProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewSamlUserAttributeProtocolMapper(mapper *SamlUserAttributeProtocolMapper) error { diff --git a/keycloak/saml_user_property_protocol_mapper.go b/keycloak/saml_user_property_protocol_mapper.go index 6be3e410..3024ca8a 100644 --- a/keycloak/saml_user_property_protocol_mapper.go +++ b/keycloak/saml_user_property_protocol_mapper.go @@ -50,7 +50,7 @@ func (protocolMapper *protocolMapper) convertToSamlUserPropertyProtocolMapper(re func (keycloakClient *KeycloakClient) GetSamlUserPropertyProtocolMapper(realmId, clientId, clientScopeId, mapperId string) (*SamlUserPropertyProtocolMapper, error) { var protocolMapper *protocolMapper - err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper) + err := keycloakClient.get(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), &protocolMapper, nil) if err != nil { return nil, err } @@ -59,7 +59,7 @@ func (keycloakClient *KeycloakClient) GetSamlUserPropertyProtocolMapper(realmId, } func (keycloakClient *KeycloakClient) DeleteSamlUserPropertyProtocolMapper(realmId, clientId, clientScopeId, mapperId string) error { - return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId)) + return keycloakClient.delete(individualProtocolMapperPath(realmId, clientId, clientScopeId, mapperId), nil) } func (keycloakClient *KeycloakClient) NewSamlUserPropertyProtocolMapper(mapper *SamlUserPropertyProtocolMapper) error { diff --git a/keycloak/server_info.go b/keycloak/server_info.go index b8a2a5c0..48b7533f 100644 --- a/keycloak/server_info.go +++ b/keycloak/server_info.go @@ -41,7 +41,7 @@ func (serverInfo *ServerInfo) ComponentTypeIsInstalled(componentType, componentT func (keycloakClient *KeycloakClient) GetServerInfo() (*ServerInfo, error) { var serverInfo ServerInfo - err := keycloakClient.get("/serverinfo", &serverInfo) + err := keycloakClient.get("/serverinfo", &serverInfo, nil) if err != nil { return nil, err } diff --git a/keycloak/user.go b/keycloak/user.go index 2a4e9bd7..bb66b755 100644 --- a/keycloak/user.go +++ b/keycloak/user.go @@ -5,15 +5,25 @@ import ( "net/url" ) +type FederatedIdentity struct { + IdentityProvider string `json:"identityProvider"` + UserId string `json:"userId"` + UserName string `json:"userName"` +} + +type FederatedIdentities []FederatedIdentity + type User struct { Id string `json:"id,omitempty"` RealmId string `json:"-"` - Username string `json:"username"` - Email string `json:"email"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - Enabled bool `json:"enabled"` + Username string `json:"username"` + Email string `json:"email"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + Enabled bool `json:"enabled"` + Attributes map[string][]string `json:"attributes"` + FederatedIdentities FederatedIdentities `json:"federatedIdentities"` } type PasswordCredentials struct { @@ -50,7 +60,7 @@ func (keycloakClient *KeycloakClient) ResetUserPassword(realmId, userId string, func (keycloakClient *KeycloakClient) GetUser(realmId, id string) (*User, error) { var user User - err := keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s", realmId, id), &user) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s", realmId, id), &user, nil) if err != nil { return nil, err } @@ -65,13 +75,13 @@ func (keycloakClient *KeycloakClient) UpdateUser(user *User) error { } func (keycloakClient *KeycloakClient) DeleteUser(realmId, id string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s", realmId, id)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s", realmId, id), nil) } func (keycloakClient *KeycloakClient) GetUserByUsername(realmId, username string) (*User, error) { var users []*User - err := keycloakClient.get(fmt.Sprintf("/realms/%s/users?username=%s", realmId, url.QueryEscape(username)), &users) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/users?username=%s", realmId, url.QueryEscape(username)), &users, nil) if err != nil { return nil, err } @@ -115,7 +125,7 @@ func (keycloakClient *KeycloakClient) AddUsersToGroup(realmId, groupId string, u } func (keycloakClient *KeycloakClient) RemoveUserFromGroup(user *User, groupId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/groups/%s", user.RealmId, user.Id, groupId)) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/groups/%s", user.RealmId, user.Id, groupId), nil) } func (keycloakClient *KeycloakClient) RemoveUsersFromGroup(realmId, groupId string, usernames []interface{}) error { diff --git a/provider/data_source_keycloak_openid_client.go b/provider/data_source_keycloak_openid_client.go new file mode 100644 index 00000000..2d141c7f --- /dev/null +++ b/provider/data_source_keycloak_openid_client.go @@ -0,0 +1,105 @@ +package provider + +import ( + "github.com/hashicorp/terraform/helper/schema" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" +) + +func dataSourceKeycloakOpenidClient() *schema.Resource { + return &schema.Resource{ + Read: dataSourceKeycloakOpenidClientRead, + + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Required: true, + }, + "realm_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "access_type": { + Type: schema.TypeString, + Computed: true, + }, + "client_secret": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + "standard_flow_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "implicit_flow_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "direct_access_grants_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "valid_redirect_uris": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Computed: true, + }, + "web_origins": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + Computed: true, + }, + "service_accounts_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "authorization": { + Type: schema.TypeSet, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "policy_enforcement_mode": { + Type: schema.TypeString, + Computed: true, + }, + "allow_remote_resource_management": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + + client, err := keycloakClient.GetClientByName(realmId, clientId) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientData(data, client) + + return nil +} diff --git a/provider/data_source_keycloak_openid_client_authorization_policy.go b/provider/data_source_keycloak_openid_client_authorization_policy.go new file mode 100644 index 00000000..1eba98ee --- /dev/null +++ b/provider/data_source_keycloak_openid_client_authorization_policy.go @@ -0,0 +1,90 @@ +package provider + +import ( + "github.com/hashicorp/terraform/helper/schema" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" +) + +func dataSourceKeycloakOpenidClientAuthorizationPolicy() *schema.Resource { + return &schema.Resource{ + Read: dataSourceKeycloakOpenidClientAuthorizationPolicyRead, + + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Required: true, + }, + "realm_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "decision_strategy": { + Type: schema.TypeString, + Computed: true, + }, + "owner": { + Type: schema.TypeString, + Computed: true, + }, + "logic": { + Type: schema.TypeString, + Computed: true, + }, + "policies": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + "resources": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + "scopes": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func setOpenidClientAuthorizationPolicyData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationPolicy) { + data.SetId(policy.Id) + + data.Set("client_id", policy.ClientId) + data.Set("realm_id", policy.RealmId) + data.Set("name", policy.Name) + data.Set("decision_strategy", policy.DecisionStrategy) + data.Set("owner", policy.Owner) + data.Set("logic", policy.Logic) + data.Set("policies", policy.Policies) + data.Set("resources", policy.Resources) + data.Set("scopes", policy.Scopes) + data.Set("type", policy.Type) +} + +func dataSourceKeycloakOpenidClientAuthorizationPolicyRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + name := data.Get("name").(string) + + client, err := keycloakClient.GetClientAuthorizationPolicyByName(realmId, clientId, name) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientAuthorizationPolicyData(data, client) + + return nil +} diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 1446811e..df350f05 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -10,7 +10,8 @@ import ( ) var ( - keycloakOpenidClientAccessTypes = []string{"CONFIDENTIAL", "PUBLIC", "BEARER-ONLY"} + keycloakOpenidClientAccessTypes = []string{"CONFIDENTIAL", "PUBLIC", "BEARER-ONLY"} + keycloakOpenidClientAuthorizationPolicyEnforcementMode = []string{"ENFORCING", "PERMISSIVE", "DISABLED"} ) func resourceKeycloakOpenidClient() *schema.Resource { @@ -72,16 +73,6 @@ func resourceKeycloakOpenidClient() *schema.Resource { Optional: true, Default: false, }, - "service_accounts_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "authorization_services_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, "valid_redirect_uris": { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, @@ -94,46 +85,27 @@ func resourceKeycloakOpenidClient() *schema.Resource { Set: schema.HashString, Optional: true, }, - "resource": { + "service_accounts_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "authorization": { Type: schema.TypeSet, Optional: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "display_name": { - Type: schema.TypeString, - Required: true, - }, - "name": { - Type: schema.TypeString, - Required: true, + "policy_enforcement_mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(keycloakOpenidClientAuthorizationPolicyEnforcementMode, false), }, - "uris": { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - }, - "icon_uri": { - Type: schema.TypeString, - Optional: true, - }, - "id": { - Type: schema.TypeString, - Computed: true, - }, - "owner_managed_access": { + "allow_remote_resource_management": { Type: schema.TypeBool, Optional: true, Default: false, }, - "scopes": { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - }, - "attributes": { - Type: schema.TypeMap, - Optional: true, - }, }, }, }, @@ -141,9 +113,9 @@ func resourceKeycloakOpenidClient() *schema.Resource { } } -func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, *keycloak.OpenidClientResourcesDiff, error) { - var validRedirectUris []string - var webOrigins []string +func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, error) { + validRedirectUris := make([]string, 0) + webOrigins := make([]string, 0) if v, ok := data.GetOk("valid_redirect_uris"); ok { for _, validRedirectUri := range v.(*schema.Set).List() { @@ -158,20 +130,31 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } openidClient := &keycloak.OpenidClient{ - Id: data.Id(), - ClientId: data.Get("client_id").(string), - RealmId: data.Get("realm_id").(string), - Name: data.Get("name").(string), - Enabled: data.Get("enabled").(bool), - Description: data.Get("description").(string), - AuthorizationServicesEnabled: data.Get("authorization_services_enabled").(bool), - ClientSecret: data.Get("client_secret").(string), - StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), - ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), - DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), - ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), - ValidRedirectUris: validRedirectUris, - WebOrigins: webOrigins, + Id: data.Id(), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + Name: data.Get("name").(string), + Enabled: data.Get("enabled").(bool), + Description: data.Get("description").(string), + ClientSecret: data.Get("client_secret").(string), + StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), + ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), + DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), + ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), + ValidRedirectUris: validRedirectUris, + WebOrigins: webOrigins, + } + + if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled { + if _, ok := data.GetOk("valid_redirect_uris"); ok { + return nil, errors.New("valid_redirect_uris cannot be set when standard or implicit flow is not enabled") + } + } + + if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled && !openidClient.DirectAccessGrantsEnabled { + if _, ok := data.GetOk("web_origins"); ok { + return nil, errors.New("web_origins cannot be set when standard or implicit flow is not enabled") + } } // access type @@ -181,73 +164,21 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, openidClient.BearerOnly = true } - resources := &keycloak.OpenidClientResourcesDiff{} - unchangedResourcesData := new(schema.Set) - if v, ok := data.GetOk("resource"); ok && data.HasChange("resource") { - if openidClient.AuthorizationServicesEnabled { - unchangedResourcesData = v.(*schema.Set) - } else { - return nil, nil, errors.New("Resources cannot be managed when aunothiztion is not enabled") + if v, ok := data.GetOk("authorization"); ok { + openidClient.AuthorizationServicesEnabled = true + authorizationSettingsData := v.(*schema.Set).List()[0] + authorizationSettings := authorizationSettingsData.(map[string]interface{}) + openidClient.AuthorizationSettings = keycloak.OpenidClientAuthorizationSettings{ + PolicyEnforcementMode: authorizationSettings["policy_enforcement_mode"].(string), + AllowRemoteResourceManagement: authorizationSettings["allow_remote_resource_management"].(bool), } + } else { + openidClient.AuthorizationServicesEnabled = false } - if data.HasChange("resource") { - o, n := data.GetChange("resource") - if o == nil { - o = new(schema.Set) - } - if n == nil { - n = new(schema.Set) - } - unchangedResourcesData = unchangedResourcesData.Difference(n.(*schema.Set)) - removeResourcesData := o.(*schema.Set).Difference(n.(*schema.Set)).Difference(unchangedResourcesData).List() - resources.Remove = *getOpenidClientResourcesFromData(removeResourcesData) - addResourcesData := n.(*schema.Set).Difference(o.(*schema.Set)).Difference(unchangedResourcesData).List() - resources.Add = *getOpenidClientResourcesFromData(addResourcesData) - } - - resources.Unchanged = *getOpenidClientResourcesFromData(unchangedResourcesData.List()) - - return openidClient, resources, nil -} - -func getOpenidClientResourcesFromData(data []interface{}) *keycloak.OpenidClientResources { - var resources keycloak.OpenidClientResources - for _, d := range data { - resourceData := d.(map[string]interface{}) - var uris []string - var scopes []string - attributes := map[string][]string{} - if v, ok := resourceData["uris"]; ok { - for _, uri := range v.([]interface{}) { - uris = append(uris, uri.(string)) - } - } - if v, ok := resourceData["scopes"]; ok { - for _, scope := range v.([]interface{}) { - scopes = append(scopes, scope.(string)) - } - } - if v, ok := resourceData["attributes"]; ok { - for key, value := range v.(map[string]interface{}) { - attributes[key] = strings.Split(value.(string), ",") - } - } - resource := keycloak.OpenidClientResource{ - DisplayName: resourceData["display_name"].(string), - Name: resourceData["name"].(string), - IconUri: resourceData["icon_uri"].(string), - OwnerManagedAccess: resourceData["owner_managed_access"].(bool), - Id: resourceData["id"].(string), - Uris: uris, - Scopes: scopes, - Attributes: attributes, - } - resources = append(resources, resource) - } - return &resources + return openidClient, nil } -func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, resources *keycloak.OpenidClientResources) { +func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient) { data.SetId(client.Id) data.Set("client_id", client.ClientId) @@ -272,29 +203,12 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien } else { data.Set("access_type", "CONFIDENTIAL") } - - resourcesData := []interface{}{} - - for _, resource := range *resources { - resourceData := map[string]interface{}{ - "display_name": resource.DisplayName, - "name": resource.Name, - "uris": resource.Uris, - "icon_uri": resource.IconUri, - "owner_managed_access": resource.OwnerManagedAccess, - "scopes": resource.Scopes, - "attributes": listValueToStr(resource.Attributes), - "id": resource.Id, - } - resourcesData = append(resourcesData, resourceData) - } - data.Set("resource", resourcesData) } func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client, resources, err := getOpenidClientFromData(data) + client, err := getOpenidClientFromData(data) if err != nil { return err } @@ -309,14 +223,7 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - for i := 0; i < len((*resources).Add); i++ { - err = keycloakClient.NewOpenidClientResource(client, &((*resources).Add)[i]) - if err != nil { - return err - } - } - - setOpenidClientData(data, client, &resources.Add) + setOpenidClientData(data, client) return resourceKeycloakOpenidClientRead(data, meta) } @@ -332,16 +239,7 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ return handleNotFoundError(err, data) } - resources := &keycloak.OpenidClientResources{} - - if client.AuthorizationServicesEnabled { - resources, err = keycloakClient.GetOpenidClientResources(realmId, id) - if err != nil { - return handleNotFoundError(err, data) - } - } - - setOpenidClientData(data, client, resources) + setOpenidClientData(data, client) return nil } @@ -349,7 +247,7 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interface{}) error { keycloakClient := meta.(*keycloak.KeycloakClient) - client, resources, err := getOpenidClientFromData(data) + client, err := getOpenidClientFromData(data) if err != nil { return err } @@ -364,30 +262,7 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac return err } - if client.AuthorizationServicesEnabled { - for _, resource := range (*resources).Unchanged { - err = keycloakClient.UpdateOpenidClientResource(client, &resource) - if err != nil { - return err - } - } - - for _, resource := range (*resources).Add { - err = keycloakClient.NewOpenidClientResource(client, &resource) - if err != nil { - return err - } - } - - for _, resource := range (*resources).Remove { - err = keycloakClient.DeleteOpenidClientResource(client.RealmId, client.Id, resource.Id) - if err != nil { - return err - } - } - } - - setOpenidClientData(data, client, &resources.Unchanged) + setOpenidClientData(data, client) return nil } diff --git a/provider/keycloak_openid_client_authorization_permission.go b/provider/keycloak_openid_client_authorization_permission.go new file mode 100644 index 00000000..88d09aed --- /dev/null +++ b/provider/keycloak_openid_client_authorization_permission.go @@ -0,0 +1,177 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "strings" +) + +var ( + keycloakOpenidClientResourcePermissionDecisionStrategies = []string{"UNANIMOUS", "AFFIRMATIVE", "CONSENSUS"} + keycloakOpenidClientPermissionTypes = []string{"resource", "scope"} +) + +func resourceKeycloakOpenidClientAuthorizationPermission() *schema.Resource { + return &schema.Resource{ + Create: resourceKeycloakOpenidClientAuthorizationPermissionCreate, + Read: resourceKeycloakOpenidClientAuthorizationPermissionRead, + Delete: resourceKeycloakOpenidClientAuthorizationPermissionDelete, + Update: resourceKeycloakOpenidClientAuthorizationPermissionUpdate, + // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + Importer: &schema.ResourceImporter{ + State: resourceKeycloakOpenidClientAuthorizationPermissionImport, + }, + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "realm_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "decision_strategy": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(keycloakOpenidClientResourcePermissionDecisionStrategies, false), + Default: "UNANIMOUS", + }, + "policies": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "resources": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "type": { + Type: schema.TypeString, + Optional: true, + Default: "resource", + ValidateFunc: validation.StringInSlice(keycloakOpenidClientPermissionTypes, false), + }, + }, + } +} + +func getOpenidClientAuthorizationPermissionFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationPermission { + var policies []string + var resources []string + if v, ok := data.GetOk("resources"); ok { + for _, resource := range v.([]interface{}) { + resources = append(resources, resource.(string)) + } + } + if v, ok := data.GetOk("policies"); ok { + for _, policy := range v.([]interface{}) { + policies = append(policies, policy.(string)) + } + } + permission := keycloak.OpenidClientAuthorizationPermission{ + Id: data.Id(), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + Description: data.Get("description").(string), + Name: data.Get("name").(string), + DecisionStrategy: data.Get("decision_strategy").(string), + Type: data.Get("type").(string), + Policies: policies, + Resources: resources, + } + return &permission +} + +func setOpenidClientAuthorizationPermissionData(data *schema.ResourceData, permission *keycloak.OpenidClientAuthorizationPermission) { + data.SetId(permission.Id) + data.Set("client_id", permission.ClientId) + data.Set("realm_id", permission.RealmId) + data.Set("description", permission.Description) + data.Set("name", permission.Name) + data.Set("decision_strategy", permission.DecisionStrategy) + data.Set("type", permission.Type) + data.Set("policies", permission.Policies) + data.Set("resources", permission.Resources) +} + +func resourceKeycloakOpenidClientAuthorizationPermissionCreate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + permission := getOpenidClientAuthorizationPermissionFromData(data) + + err := keycloakClient.NewOpenidClientAuthorizationPermission(permission) + if err != nil { + return err + } + + setOpenidClientAuthorizationPermissionData(data, permission) + + return resourceKeycloakOpenidClientAuthorizationPermissionRead(data, meta) +} + +func resourceKeycloakOpenidClientAuthorizationPermissionRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + id := data.Id() + + permission, err := keycloakClient.GetOpenidClientAuthorizationPermission(realmId, clientId, id) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientAuthorizationPermissionData(data, permission) + + return nil +} + +func resourceKeycloakOpenidClientAuthorizationPermissionUpdate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + permission := getOpenidClientAuthorizationPermissionFromData(data) + + err := keycloakClient.UpdateOpenidClientAuthorizationPermission(permission) + if err != nil { + return err + } + + setOpenidClientAuthorizationPermissionData(data, permission) + + return nil +} + +func resourceKeycloakOpenidClientAuthorizationPermissionDelete(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + id := data.Id() + + return keycloakClient.DeleteOpenidClientAuthorizationPermission(realmId, clientId, id) +} + +func resourceKeycloakOpenidClientAuthorizationPermissionImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + if len(parts) != 3 { + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{clientId}}/{{permissionId}}") + } + d.Set("realm_id", parts[0]) + d.Set("client_id", parts[1]) + d.SetId(parts[3]) + + return []*schema.ResourceData{d}, nil +} diff --git a/provider/keycloak_openid_client_authorization_resource.go b/provider/keycloak_openid_client_authorization_resource.go new file mode 100644 index 00000000..c4bd4c7e --- /dev/null +++ b/provider/keycloak_openid_client_authorization_resource.go @@ -0,0 +1,192 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "strings" +) + +func resourceKeycloakOpenidClientAuthorizationResource() *schema.Resource { + return &schema.Resource{ + Create: resourceKeycloakOpenidClientAuthorizationResourceCreate, + Read: resourceKeycloakOpenidClientAuthorizationResourceRead, + Delete: resourceKeycloakOpenidClientAuthorizationResourceDelete, + Update: resourceKeycloakOpenidClientAuthorizationResourceUpdate, + // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + Importer: &schema.ResourceImporter{ + State: resourceKeycloakOpenidClientAuthorizationResourceImport, + }, + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "realm_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "display_name": { + Type: schema.TypeString, + Optional: true, + }, + "uris": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "icon_uri": { + Type: schema.TypeString, + Optional: true, + }, + "owner_managed_access": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "scopes": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "type": { + Type: schema.TypeString, + Optional: true, + }, + "attributes": { + Type: schema.TypeMap, + Optional: true, + }, + }, + } +} + +func getOpenidClientAuthorizationResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationResource { + var uris []string + var scopes []keycloak.OpenidClientAuthorizationScope + attributes := map[string][]string{} + if v, ok := data.GetOk("uris"); ok { + for _, uri := range v.([]interface{}) { + uris = append(uris, uri.(string)) + } + } + if v, ok := data.GetOk("scopes"); ok { + for _, scope := range v.([]string) { + scopes = append(scopes, keycloak.OpenidClientAuthorizationScope{ + Name: scope, + }) + } + } + if v, ok := data.GetOk("attributes"); ok { + for key, value := range v.(map[string]interface{}) { + attributes[key] = strings.Split(value.(string), ",") + } + } + resource := keycloak.OpenidClientAuthorizationResource{ + Id: data.Id(), + DisplayName: data.Get("display_name").(string), + Name: data.Get("name").(string), + IconUri: data.Get("icon_uri").(string), + OwnerManagedAccess: data.Get("owner_managed_access").(bool), + Type: data.Get("type").(string), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + Uris: uris, + Scopes: scopes, + Attributes: attributes, + } + return &resource +} + +func setOpenidClientAuthorizationResourceData(data *schema.ResourceData, resource *keycloak.OpenidClientAuthorizationResource) { + scopes := []string{} + for _, scope := range resource.Scopes { + scopes = append(scopes, scope.Name) + } + data.SetId(resource.Id) + data.Set("client_id", resource.ClientId) + data.Set("realm_id", resource.RealmId) + data.Set("display_name", resource.DisplayName) + data.Set("name", resource.Name) + data.Set("icon_uri", resource.IconUri) + data.Set("owner_managed_access", resource.OwnerManagedAccess) + data.Set("type", resource.Type) + data.Set("uris", resource.Uris) + data.Set("attributes", resource.Attributes) + data.Set("scopes", scopes) +} + +func resourceKeycloakOpenidClientAuthorizationResourceCreate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + resource := getOpenidClientAuthorizationResourceFromData(data) + + err := keycloakClient.NewOpenidClientAuthorizationResource(resource) + if err != nil { + return err + } + + setOpenidClientAuthorizationResourceData(data, resource) + + return resourceKeycloakOpenidClientAuthorizationResourceRead(data, meta) +} + +func resourceKeycloakOpenidClientAuthorizationResourceRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + id := data.Id() + + resource, err := keycloakClient.GetOpenidClientAuthorizationResource(realmId, clientId, id) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientAuthorizationResourceData(data, resource) + + return nil +} + +func resourceKeycloakOpenidClientAuthorizationResourceUpdate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + resource := getOpenidClientAuthorizationResourceFromData(data) + + err := keycloakClient.UpdateOpenidClientAuthorizationResource(resource) + if err != nil { + return err + } + + setOpenidClientAuthorizationResourceData(data, resource) + + return nil +} + +func resourceKeycloakOpenidClientAuthorizationResourceDelete(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + id := data.Id() + + return keycloakClient.DeleteOpenidClientAuthorizationResource(realmId, clientId, id) +} + +func resourceKeycloakOpenidClientAuthorizationResourceImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + if len(parts) != 3 { + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{clientId}}/{{authorizationResourceId}}") + } + d.Set("realm_id", parts[0]) + d.Set("client_id", parts[1]) + d.SetId(parts[3]) + + return []*schema.ResourceData{d}, nil +} diff --git a/provider/keycloak_openid_client_authorization_scope.go b/provider/keycloak_openid_client_authorization_scope.go new file mode 100644 index 00000000..4fc8e92a --- /dev/null +++ b/provider/keycloak_openid_client_authorization_scope.go @@ -0,0 +1,135 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "strings" +) + +func resourceKeycloakOpenidClientAuthorizationScope() *schema.Resource { + return &schema.Resource{ + Create: resourceKeycloakOpenidClientAuthorizationScopeCreate, + Read: resourceKeycloakOpenidClientAuthorizationScopeRead, + Delete: resourceKeycloakOpenidClientAuthorizationScopeDelete, + Update: resourceKeycloakOpenidClientAuthorizationScopeUpdate, + // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + Importer: &schema.ResourceImporter{ + State: resourceKeycloakOpenidClientAuthorizationScopeImport, + }, + Schema: map[string]*schema.Schema{ + "client_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "realm_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "display_name": { + Type: schema.TypeString, + Optional: true, + }, + "icon_uri": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func getOpenidClientAuthorizationScopeFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationScope { + scope := keycloak.OpenidClientAuthorizationScope{ + DisplayName: data.Get("display_name").(string), + Name: data.Get("name").(string), + IconUri: data.Get("icon_uri").(string), + Id: data.Id(), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + } + return &scope +} + +func setOpenidClientAuthorizationScopeData(data *schema.ResourceData, scope *keycloak.OpenidClientAuthorizationScope) { + data.SetId(scope.Id) + data.Set("client_id", scope.ClientId) + data.Set("realm_id", scope.RealmId) + data.Set("display_name", scope.DisplayName) + data.Set("name", scope.Name) + data.Set("icon_uri", scope.IconUri) +} + +func resourceKeycloakOpenidClientAuthorizationScopeCreate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + scope := getOpenidClientAuthorizationScopeFromData(data) + + err := keycloakClient.NewOpenidClientAuthorizationScope(scope) + if err != nil { + return err + } + + setOpenidClientAuthorizationScopeData(data, scope) + + return resourceKeycloakOpenidClientAuthorizationScopeRead(data, meta) +} + +func resourceKeycloakOpenidClientAuthorizationScopeRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + id := data.Id() + + scope, err := keycloakClient.GetOpenidClientAuthorizationScope(realmId, clientId, id) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientAuthorizationScopeData(data, scope) + + return nil +} + +func resourceKeycloakOpenidClientAuthorizationScopeUpdate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + scope := getOpenidClientAuthorizationScopeFromData(data) + + err := keycloakClient.UpdateOpenidClientAuthorizationScope(scope) + if err != nil { + return err + } + + setOpenidClientAuthorizationScopeData(data, scope) + + return nil +} + +func resourceKeycloakOpenidClientAuthorizationScopeDelete(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + clientId := data.Get("client_id").(string) + id := data.Id() + + return keycloakClient.DeleteOpenidClientAuthorizationScope(realmId, clientId, id) +} + +func resourceKeycloakOpenidClientAuthorizationScopeImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + if len(parts) != 3 { + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{clientId}}/{{authorizationScopeId}}") + } + d.Set("realm_id", parts[0]) + d.Set("client_id", parts[1]) + d.SetId(parts[3]) + + return []*schema.ResourceData{d}, nil +} diff --git a/provider/keycloak_openid_client_service_account_role.go b/provider/keycloak_openid_client_service_account_role.go new file mode 100644 index 00000000..18aae503 --- /dev/null +++ b/provider/keycloak_openid_client_service_account_role.go @@ -0,0 +1,113 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "strings" +) + +func resourceKeycloakOpenidClientServiceAccountRole() *schema.Resource { + return &schema.Resource{ + Create: resourceKeycloakOpenidClientServiceAccountRoleCreate, + Read: resourceKeycloakOpenidClientServiceAccountRoleRead, + Delete: resourceKeycloakOpenidClientServiceAccountRoleDelete, + // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + Importer: &schema.ResourceImporter{ + State: resourceKeycloakOpenidClientServiceAccountRoleImport, + }, + Schema: map[string]*schema.Schema{ + "source_client_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "realm_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "target_client_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "role": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func getOpenidClientServiceAccountRoleFromData(data *schema.ResourceData) *keycloak.OpenidClientServiceAccountRole { + return &keycloak.OpenidClientServiceAccountRole{ + Id: data.Id(), + ContainerId: data.Get("source_client_id").(string), + Name: data.Get("role").(string), + RealmId: data.Get("realm_id").(string), + ClientId: data.Get("target_client_id").(string), + } +} + +func setOpenidClientServiceAccountRoleData(data *schema.ResourceData, serviceAccountRole *keycloak.OpenidClientServiceAccountRole) { + data.SetId(serviceAccountRole.Id) + data.Set("realm_id", serviceAccountRole.RealmId) + data.Set("source_client_id", serviceAccountRole.ContainerId) + data.Set("target_client_id", serviceAccountRole.ClientId) + data.Set("role", serviceAccountRole.Name) +} + +func resourceKeycloakOpenidClientServiceAccountRoleCreate(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + serviceAccountRole := getOpenidClientServiceAccountRoleFromData(data) + err := keycloakClient.NewOpenidClientServiceAccountRole(serviceAccountRole) + if err != nil { + return err + } + setOpenidClientServiceAccountRoleData(data, serviceAccountRole) + return resourceKeycloakOpenidClientServiceAccountRoleRead(data, meta) +} + +func resourceKeycloakOpenidClientServiceAccountRoleRead(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + sourceClientId := data.Get("source_client_id").(string) + targetClientId := data.Get("target_client_id").(string) + id := data.Id() + + serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, sourceClientId, targetClientId, id) + if err != nil { + return handleNotFoundError(err, data) + } + + setOpenidClientServiceAccountRoleData(data, serviceAccountRole) + + return nil +} + +func resourceKeycloakOpenidClientServiceAccountRoleDelete(data *schema.ResourceData, meta interface{}) error { + keycloakClient := meta.(*keycloak.KeycloakClient) + + realmId := data.Get("realm_id").(string) + sourceClientId := data.Get("source_client_id").(string) + targetClientId := data.Get("target_client_id").(string) + id := data.Id() + + return keycloakClient.DeleteOpenidClientServiceAccountRole(realmId, sourceClientId, targetClientId, id) +} + +func resourceKeycloakOpenidClientServiceAccountRoleImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { + parts := strings.Split(d.Id(), "/") + if len(parts) != 3 { + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{sourceClientId}}/{{targetClientId}}/{{role}}") + } + d.Set("realm_id", parts[0]) + d.Set("source_client_id", parts[1]) + d.Set("target_client_id", parts[2]) + d.SetId(parts[3]) + + return []*schema.ResourceData{d}, nil +} diff --git a/provider/keycloak_user.go b/provider/keycloak_user.go index da396b7d..e9db4ed5 100644 --- a/provider/keycloak_user.go +++ b/provider/keycloak_user.go @@ -49,6 +49,30 @@ func resourceKeycloakUser() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "attributes": { + Type: schema.TypeMap, + Optional: true, + }, + "federated_identity": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "identity_provider": { + Type: schema.TypeString, + Required: true, + }, + "user_id": { + Type: schema.TypeString, + Required: true, + }, + "user_name": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, "initial_password": { Type: schema.TypeList, Optional: true, @@ -83,15 +107,44 @@ func onlyDiffOnCreate(_, _, _ string, d *schema.ResourceData) bool { } func mapFromDataToUser(data *schema.ResourceData) *keycloak.User { + attributes := map[string][]string{} + if v, ok := data.GetOk("attributes"); ok { + for key, value := range v.(map[string]interface{}) { + attributes[key] = strings.Split(value.(string), ",") + } + } + + federatedIdentities := &keycloak.FederatedIdentities{} + + if v, ok := data.GetOk("federated_identity"); ok { + federatedIdentities = getUserFederatedIdentitiesFromData(v.(*schema.Set).List()) + } + return &keycloak.User{ - Id: data.Id(), - RealmId: data.Get("realm_id").(string), - Username: data.Get("username").(string), - Email: data.Get("email").(string), - FirstName: data.Get("first_name").(string), - LastName: data.Get("last_name").(string), - Enabled: data.Get("enabled").(bool), + Id: data.Id(), + RealmId: data.Get("realm_id").(string), + Username: data.Get("username").(string), + Email: data.Get("email").(string), + FirstName: data.Get("first_name").(string), + LastName: data.Get("last_name").(string), + Enabled: data.Get("enabled").(bool), + Attributes: attributes, + FederatedIdentities: *federatedIdentities, + } +} + +func getUserFederatedIdentitiesFromData(data []interface{}) *keycloak.FederatedIdentities { + var federatedIdentities keycloak.FederatedIdentities + for _, d := range data { + federatedIdentitiesData := d.(map[string]interface{}) + federatedIdentity := keycloak.FederatedIdentity{ + IdentityProvider: federatedIdentitiesData["display_name"].(string), + UserId: federatedIdentitiesData["name"].(string), + UserName: federatedIdentitiesData["icon_uri"].(string), + } + federatedIdentities = append(federatedIdentities, federatedIdentity) } + return &federatedIdentities } func mapFromUserToData(data *schema.ResourceData, user *keycloak.User) { diff --git a/provider/provider.go b/provider/provider.go index f5b0be72..2b3c28b9 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -7,6 +7,10 @@ import ( func KeycloakProvider() *schema.Provider { return &schema.Provider{ + DataSourcesMap: map[string]*schema.Resource{ + "keycloak_openid_client": dataSourceKeycloakOpenidClient(), + "keycloak_openid_client_authorization_policy": dataSourceKeycloakOpenidClientAuthorizationPolicy(), + }, ResourcesMap: map[string]*schema.Resource{ "keycloak_realm": resourceKeycloakRealm(), "keycloak_group": resourceKeycloakGroup(), @@ -38,6 +42,10 @@ func KeycloakProvider() *schema.Provider { "keycloak_user_template_importer_identity_provider_mapper": resourceKeycloakUserTemplateImporterIdentityProviderMapper(), "keycloak_saml_identity_provider": resourceKeycloakSamlIdentityProvider(), "keycloak_oidc_identity_provider": resourceKeycloakOidcIdentityProvider(), + "keycloak_openid_client_authorization_resource": resourceKeycloakOpenidClientAuthorizationResource(), + "keycloak_openid_client_authorization_scope": resourceKeycloakOpenidClientAuthorizationScope(), + "keycloak_openid_client_authorization_permission": resourceKeycloakOpenidClientAuthorizationPermission(), + "keycloak_openid_client_service_account_role": resourceKeycloakOpenidClientServiceAccountRole(), }, Schema: map[string]*schema.Schema{ "client_id": { From a96715e803954f4ec17557ea52c4d01c8dd0cd33 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Mon, 29 Apr 2019 23:41:17 +0300 Subject: [PATCH 10/47] added examples --- example/main.tf | 96 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/example/main.tf b/example/main.tf index 76958d6a..cf9fbfd5 100644 --- a/example/main.tf +++ b/example/main.tf @@ -89,28 +89,6 @@ resource "keycloak_openid_client" "test_client" { client_secret = "secret" } -resource "keycloak_openid_client" "test_resource_client" { - client_id = "test-openid-client1" - name = "test-openid-client1" - realm_id = "${keycloak_realm.test.id}" - description = "a test openid client" - - access_type = "CONFIDENTIAL" - direct_access_grants_enabled = true - service_accounts_enabled = true - - valid_redirect_uris = [ - "http://localhost:5555/callback", - ] - - resource { - name = "new" - display_name = "new" - } - - client_secret = "secret" -} - resource "keycloak_openid_client_scope" "test_default_client_scope" { name = "test-default-client-scope" realm_id = "${keycloak_realm.test.id}" @@ -466,3 +444,77 @@ resource keycloak_hardcoded_attribute_identity_provider_mapper saml { attribute_value = "value" user_session = false } + +data "keycloak_openid_client" "broker" { + realm_id = "${keycloak_realm.test.id}" + client_id = "broker" +} + +data "keycloak_openid_client_authorization_policy" "default" { + realm_id = "${keycloak_realm.test.id}" + client_id = "${keycloak_openid_client.test_client_auth.id}" + name = "default" +} + +resource "keycloak_openid_client" "test_client_auth" { + client_id = "test-client-auth" + name = "test-client-auth" + realm_id = "${keycloak_realm.test.id}" + description = "a test openid client" + + access_type = "CONFIDENTIAL" + direct_access_grants_enabled = true + service_accounts_enabled = true + implicit_flow_enabled = true + + valid_redirect_uris = [ + "http://localhost:5555/callback", + ] + + authorization { + policy_enforcement_mode = "ENFORCING" + } + + client_secret = "secret" +} + +resource "keycloak_openid_client_authorization_permission" "resource" { + client_id = "${keycloak_openid_client.test_client_auth.id}" + realm_id = "${keycloak_realm.test.id}" + name = "test" + policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] + resources = ["${keycloak_openid_client_authorization_resource.resource.id}"] +} + +resource "keycloak_openid_client_authorization_resource" "resource" { + client_id = "${keycloak_openid_client.test_client_auth.id}" + name = "test-openid-client1" + realm_id = "${keycloak_realm.test.id}" + uris = [ + "/shit/*" + ] + attributes = { + "asdads" = "asdasd" + } +} + +resource "keycloak_openid_client_authorization_scope" "resource" { + client_id = "${keycloak_openid_client.test_client_auth.id}" + name = "test-openid-client1" + realm_id = "${keycloak_realm.test.id}" +} + +resource "keycloak_user" "resource" { + realm_id = "${keycloak_realm.test.id}" + username = "test" + attributes = { + "key" = "value" + } +} + +resource "keycloak_openid_client_service_account_role" "read_token" { + realm_id = "${keycloak_realm.test.id}" + source_client_id = "${data.keycloak_openid_client.broker.id}" + target_client_id = "${keycloak_openid_client.test_client_auth.id}" + role = "read-token" +} From ae21d6282f4e321f1babfc1463222b1241521b6a Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 00:44:46 +0300 Subject: [PATCH 11/47] updated endpoints --- keycloak/openid_client.go | 8 ++++---- provider/keycloak_openid_client.go | 12 ------------ 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index c319ba80..87d95eb3 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -125,7 +125,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(rea ClientId: clientId, Id: id, } - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, clientId, id), &permission, nil) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realm, clientId, id), &permission, nil) if err != nil { return nil, err } @@ -133,7 +133,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(rea } func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource", permission.RealmId, permission.ClientId), permission) + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission", permission.RealmId, permission.ClientId), permission) if err != nil { return err } @@ -145,7 +145,7 @@ func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(per } func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ClientId, permission.Id), permission) + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", permission.RealmId, permission.ClientId, permission.Id), permission) if err != nil { return err } @@ -153,7 +153,7 @@ func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission( } func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationPermission(realmId, clientId, permissionId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realmId, clientId, permissionId), nil) + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realmId, clientId, permissionId), nil) } func (keycloakClient *KeycloakClient) GetClientRoleByName(realm, clientId, name string) (*OpenidClientRole, error) { diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index e3a9e560..df350f05 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -157,18 +157,6 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } } - if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled { - if _, ok := data.GetOk("valid_redirect_uris"); ok { - return nil, nil, errors.New("valid_redirect_uris cannot be set when standard or implicit flow is not enabled") - } - } - - if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled && !openidClient.DirectAccessGrantsEnabled { - if _, ok := data.GetOk("web_origins"); ok { - return nil, nil, errors.New("web_origins cannot be set when standard or implicit flow is not enabled") - } - } - // access type if accessType := data.Get("access_type").(string); accessType == "PUBLIC" { openidClient.PublicClient = true From 2ca6644191703e91673425f5fed2951127b76841 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 11:08:49 +0300 Subject: [PATCH 12/47] minor fix --- keycloak/openid_client.go | 31 ++++++++++++++++++++++++++---- provider/keycloak_openid_client.go | 7 +------ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 87d95eb3..568e4014 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -100,8 +100,8 @@ type OpenidClient struct { DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` - ValidRedirectUris []string `json:"redirectUris,omitempty"` - WebOrigins []string `json:"webOrigins,omitempty"` + ValidRedirectUris []string `json:"redirectUris"` + WebOrigins []string `json:"webOrigins"` AuthorizationSettings OpenidClientAuthorizationSettings `json:"authorizationSettings,omitempty"` } @@ -125,10 +125,33 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(rea ClientId: clientId, Id: id, } - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realm, clientId, id), &permission, nil) + + policies := []OpenidClientAuthorizationPolicy{} + resources := []OpenidClientAuthorizationResource{} + + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, clientId, id), &permission, nil) + if err != nil { + return nil, err + } + + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/%s/associatedPolicies", realm, clientId, id), &policies, nil) + if err != nil { + return nil, err + } + + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s/resources", realm, clientId, id), &resources, nil) if err != nil { return nil, err } + + for _, policy := range policies { + permission.Policies = append(permission.Policies, policy.Id) + } + + for _, resource := range resources { + permission.Resources = append(permission.Resources, resource.Id) + } + return &permission, nil } @@ -145,7 +168,7 @@ func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(per } func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", permission.RealmId, permission.ClientId, permission.Id), permission) + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ClientId, permission.Id), permission) if err != nil { return err } diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index df350f05..4e44cb72 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -85,11 +85,6 @@ func resourceKeycloakOpenidClient() *schema.Resource { Set: schema.HashString, Optional: true, }, - "service_accounts_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, "authorization": { Type: schema.TypeSet, Optional: true, @@ -140,7 +135,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), - ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), + ServiceAccountsEnabled: true, ValidRedirectUris: validRedirectUris, WebOrigins: webOrigins, } From 6ca699f3504647aabefac249ef71d969e6989e2f Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 11:10:06 +0300 Subject: [PATCH 13/47] fixed examples --- example/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/example/main.tf b/example/main.tf index cf9fbfd5..353947ad 100644 --- a/example/main.tf +++ b/example/main.tf @@ -464,7 +464,6 @@ resource "keycloak_openid_client" "test_client_auth" { access_type = "CONFIDENTIAL" direct_access_grants_enabled = true - service_accounts_enabled = true implicit_flow_enabled = true valid_redirect_uris = [ From 558218bb562cc18616e057ec727f212b91c0fa66 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 11:13:29 +0300 Subject: [PATCH 14/47] removed unused util function --- provider/utils.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/provider/utils.go b/provider/utils.go index 8bc95de6..657f0b9f 100644 --- a/provider/utils.go +++ b/provider/utils.go @@ -4,7 +4,6 @@ import ( "github.com/hashicorp/terraform/helper/schema" "github.com/mrparkers/terraform-provider-keycloak/keycloak" "log" - "strings" "time" ) @@ -24,14 +23,6 @@ func mergeSchemas(a map[string]*schema.Schema, b map[string]*schema.Schema) map[ return result } -func listValueToStr(attributes map[string][]string) map[string]interface{} { - output := map[string]interface{}{} - for key, value := range attributes { - output[key] = strings.Join(value, ",") - } - return output -} - // Converts duration string to an int representing the number of seconds, which is used by the Keycloak API // Ex: "1h" => 3600 func getSecondsFromDurationString(s string) (int, error) { From 8edfe09a6fb578936cb6130afbbd26d6dc642b3d Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 11:16:52 +0300 Subject: [PATCH 15/47] minor fix --- provider/keycloak_openid_client.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 4e44cb72..df350f05 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -85,6 +85,11 @@ func resourceKeycloakOpenidClient() *schema.Resource { Set: schema.HashString, Optional: true, }, + "service_accounts_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, "authorization": { Type: schema.TypeSet, Optional: true, @@ -135,7 +140,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), - ServiceAccountsEnabled: true, + ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), ValidRedirectUris: validRedirectUris, WebOrigins: webOrigins, } From ea1eae28ef1cec6ebea28f59729a08352c9f8101 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 11:32:43 +0300 Subject: [PATCH 16/47] enable authorization service --- provider/keycloak_openid_client.go | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index df350f05..df3d6bab 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -130,19 +130,20 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } openidClient := &keycloak.OpenidClient{ - Id: data.Id(), - ClientId: data.Get("client_id").(string), - RealmId: data.Get("realm_id").(string), - Name: data.Get("name").(string), - Enabled: data.Get("enabled").(bool), - Description: data.Get("description").(string), - ClientSecret: data.Get("client_secret").(string), - StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), - ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), - DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), - ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), - ValidRedirectUris: validRedirectUris, - WebOrigins: webOrigins, + Id: data.Id(), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + Name: data.Get("name").(string), + Enabled: data.Get("enabled").(bool), + Description: data.Get("description").(string), + ClientSecret: data.Get("client_secret").(string), + StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), + ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), + DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), + ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), + ValidRedirectUris: validRedirectUris, + WebOrigins: webOrigins, + AuthorizationServicesEnabled: true, } if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled { @@ -165,15 +166,12 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } if v, ok := data.GetOk("authorization"); ok { - openidClient.AuthorizationServicesEnabled = true authorizationSettingsData := v.(*schema.Set).List()[0] authorizationSettings := authorizationSettingsData.(map[string]interface{}) openidClient.AuthorizationSettings = keycloak.OpenidClientAuthorizationSettings{ PolicyEnforcementMode: authorizationSettings["policy_enforcement_mode"].(string), AllowRemoteResourceManagement: authorizationSettings["allow_remote_resource_management"].(bool), } - } else { - openidClient.AuthorizationServicesEnabled = false } return openidClient, nil } From 1b257436f96a180c9808b16168a7348f81e12a23 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 23:43:40 +0300 Subject: [PATCH 17/47] minor fix --- .circleci/config.yml | 2 +- docker-compose.yml | 2 +- keycloak/openid_client.go | 38 +++++++++---------- provider/keycloak_openid_client.go | 32 ++++++++-------- ...cloak_openid_client_default_scopes_test.go | 10 ----- ...loak_openid_client_optional_scopes_test.go | 10 ----- 6 files changed, 38 insertions(+), 56 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1dd06ee3..66e1a24b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,7 +25,7 @@ jobs: test-template: &test-template docker: - image: circleci/golang:1.11.4 - - image: jboss/keycloak:4.8.3.Final + - image: jboss/keycloak:6.0.1 environment: DB_VENDOR: H2 KEYCLOAK_LOGLEVEL: DEBUG diff --git a/docker-compose.yml b/docker-compose.yml index e8674635..25d434dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,7 @@ services: ports: - 8389:389 keycloak: - image: jboss/keycloak:6.0.0 + image: jboss/keycloak:6.0.1 depends_on: - postgres - openldap diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 568e4014..803746d1 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -84,25 +84,25 @@ type OpenidClientAuthorizationSettings struct { } type OpenidClient struct { - Id string `json:"id,omitempty"` - ClientId string `json:"clientId"` - RealmId string `json:"-"` - Name string `json:"name"` - Protocol string `json:"protocol"` // always openid-connect for this resource - ClientAuthenticatorType string `json:"clientAuthenticatorType"` // always client-secret for now, don't have a need for JWT here - ClientSecret string `json:"secret,omitempty"` - Enabled bool `json:"enabled"` - Description string `json:"description"` - PublicClient bool `json:"publicClient"` - BearerOnly bool `json:"bearerOnly"` - StandardFlowEnabled bool `json:"standardFlowEnabled"` - ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` - DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` - ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` - AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` - ValidRedirectUris []string `json:"redirectUris"` - WebOrigins []string `json:"webOrigins"` - AuthorizationSettings OpenidClientAuthorizationSettings `json:"authorizationSettings,omitempty"` + Id string `json:"id,omitempty"` + ClientId string `json:"clientId"` + RealmId string `json:"-"` + Name string `json:"name"` + Protocol string `json:"protocol"` // always openid-connect for this resource + ClientAuthenticatorType string `json:"clientAuthenticatorType"` // always client-secret for now, don't have a need for JWT here + ClientSecret string `json:"secret,omitempty"` + Enabled bool `json:"enabled"` + Description string `json:"description"` + PublicClient bool `json:"publicClient"` + BearerOnly bool `json:"bearerOnly"` + StandardFlowEnabled bool `json:"standardFlowEnabled"` + ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` + DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` + ServiceAccountsEnabled bool `json:"serviceAccountsEnabled"` + AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled"` + ValidRedirectUris []string `json:"redirectUris"` + WebOrigins []string `json:"webOrigins"` + AuthorizationSettings *OpenidClientAuthorizationSettings `json:"authorizationSettings,omitempty"` } func (keycloakClient *KeycloakClient) GetClientAuthorizationPolicyByName(realmId, clientId, name string) (*OpenidClientAuthorizationPolicy, error) { diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index df3d6bab..7231f68c 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -130,20 +130,19 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } openidClient := &keycloak.OpenidClient{ - Id: data.Id(), - ClientId: data.Get("client_id").(string), - RealmId: data.Get("realm_id").(string), - Name: data.Get("name").(string), - Enabled: data.Get("enabled").(bool), - Description: data.Get("description").(string), - ClientSecret: data.Get("client_secret").(string), - StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), - ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), - DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), - ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), - ValidRedirectUris: validRedirectUris, - WebOrigins: webOrigins, - AuthorizationServicesEnabled: true, + Id: data.Id(), + ClientId: data.Get("client_id").(string), + RealmId: data.Get("realm_id").(string), + Name: data.Get("name").(string), + Enabled: data.Get("enabled").(bool), + Description: data.Get("description").(string), + ClientSecret: data.Get("client_secret").(string), + StandardFlowEnabled: data.Get("standard_flow_enabled").(bool), + ImplicitFlowEnabled: data.Get("implicit_flow_enabled").(bool), + DirectAccessGrantsEnabled: data.Get("direct_access_grants_enabled").(bool), + ServiceAccountsEnabled: data.Get("service_accounts_enabled").(bool), + ValidRedirectUris: validRedirectUris, + WebOrigins: webOrigins, } if !openidClient.ImplicitFlowEnabled && !openidClient.StandardFlowEnabled { @@ -166,12 +165,15 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, } if v, ok := data.GetOk("authorization"); ok { + openidClient.AuthorizationServicesEnabled = true authorizationSettingsData := v.(*schema.Set).List()[0] authorizationSettings := authorizationSettingsData.(map[string]interface{}) - openidClient.AuthorizationSettings = keycloak.OpenidClientAuthorizationSettings{ + openidClient.AuthorizationSettings = &keycloak.OpenidClientAuthorizationSettings{ PolicyEnforcementMode: authorizationSettings["policy_enforcement_mode"].(string), AllowRemoteResourceManagement: authorizationSettings["allow_remote_resource_management"].(bool), } + } else { + openidClient.AuthorizationServicesEnabled = false } return openidClient, nil } diff --git a/provider/keycloak_openid_client_default_scopes_test.go b/provider/keycloak_openid_client_default_scopes_test.go index 33587437..9b1d63b6 100644 --- a/provider/keycloak_openid_client_default_scopes_test.go +++ b/provider/keycloak_openid_client_default_scopes_test.go @@ -407,8 +407,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -442,8 +440,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -465,8 +461,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -523,8 +517,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "BEARER-ONLY" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -579,8 +571,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } %s diff --git a/provider/keycloak_openid_client_optional_scopes_test.go b/provider/keycloak_openid_client_optional_scopes_test.go index f7db5f29..e18cb281 100644 --- a/provider/keycloak_openid_client_optional_scopes_test.go +++ b/provider/keycloak_openid_client_optional_scopes_test.go @@ -408,8 +408,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -442,8 +440,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -465,8 +461,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -522,8 +516,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "BEARER-ONLY" - - valid_redirect_uris = ["foo"] } resource "keycloak_openid_client_scope" "client_scope" { @@ -577,8 +569,6 @@ resource "keycloak_openid_client" "client" { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" access_type = "PUBLIC" - - valid_redirect_uris = ["foo"] } %s From cb87711f226e3520ebcb9f9be9e0b2728c6e9f6a Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Tue, 30 Apr 2019 23:55:11 +0300 Subject: [PATCH 18/47] fixed tests for keycloak 6 --- provider/keycloak_openid_client_default_scopes_test.go | 1 + provider/keycloak_openid_client_optional_scopes_test.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/provider/keycloak_openid_client_default_scopes_test.go b/provider/keycloak_openid_client_default_scopes_test.go index 9b1d63b6..2eb89582 100644 --- a/provider/keycloak_openid_client_default_scopes_test.go +++ b/provider/keycloak_openid_client_default_scopes_test.go @@ -595,6 +595,7 @@ resource "keycloak_openid_client_default_scopes" "default_scopes" { "email", "roles", "web-origins", + "microprofile-jwt", "${keycloak_openid_client_scope.client_scope.name}" ] } diff --git a/provider/keycloak_openid_client_optional_scopes_test.go b/provider/keycloak_openid_client_optional_scopes_test.go index e18cb281..95c29a3d 100644 --- a/provider/keycloak_openid_client_optional_scopes_test.go +++ b/provider/keycloak_openid_client_optional_scopes_test.go @@ -424,6 +424,7 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" { "address", "phone", "offline_access", + "microprofile-jwt", "${keycloak_openid_client_scope.client_scope.name}" ] } @@ -500,6 +501,7 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" { "address", "phone", "offline_access", + "microprofile-jwt", "${keycloak_openid_client_scope.client_scope.name}" ] } @@ -532,6 +534,7 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" { "address", "phone", "offline_access", + "microprofile-jwt", "${keycloak_openid_client_scope.client_scope.name}" ] } @@ -592,6 +595,7 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" { "address", "phone", "offline_access", + "microprofile-jwt", "${keycloak_openid_client_scope.client_scope.name}" ] } From 5b540ddb3575a08bfb29f95c2accda661d8f1381 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Wed, 1 May 2019 00:05:19 +0300 Subject: [PATCH 19/47] minor fix --- provider/keycloak_openid_client_optional_scopes_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/keycloak_openid_client_optional_scopes_test.go b/provider/keycloak_openid_client_optional_scopes_test.go index 95c29a3d..bcb9c9b3 100644 --- a/provider/keycloak_openid_client_optional_scopes_test.go +++ b/provider/keycloak_openid_client_optional_scopes_test.go @@ -12,7 +12,7 @@ import ( ) // All openid clients in Keycloak will automatically have these scopes listed as "optional client scopes". -var preAssignedOptionalClientScopes = []string{"address", "phone", "offline_access"} +var preAssignedOptionalClientScopes = []string{"address", "phone", "offline_access", "microprofile-jwt"} func TestAccKeycloakOpenidClientOptionalScopes_basic(t *testing.T) { realm := "terraform-realm-" + acctest.RandString(10) From 9131e7f21659472eeeacfe818387910440930b57 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Wed, 1 May 2019 00:14:39 +0300 Subject: [PATCH 20/47] fixed tests --- provider/keycloak_openid_client_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/provider/keycloak_openid_client_test.go b/provider/keycloak_openid_client_test.go index 889f56ab..0748bd1a 100644 --- a/provider/keycloak_openid_client_test.go +++ b/provider/keycloak_openid_client_test.go @@ -500,8 +500,6 @@ resource "keycloak_openid_client" "client" { implicit_flow_enabled = %t direct_access_grants_enabled = %t service_accounts_enabled = %t - - valid_redirect_uris = %s web_origins = %s } `, openidClient.RealmId, openidClient.ClientId, openidClient.Name, openidClient.Enabled, openidClient.Description, openidClient.ClientSecret, openidClient.StandardFlowEnabled, openidClient.ImplicitFlowEnabled, openidClient.ServiceAccountsEnabled, openidClient.DirectAccessGrantsEnabled, arrayOfStringsForTerraformResource(openidClient.ValidRedirectUris), arrayOfStringsForTerraformResource(openidClient.WebOrigins)) From fdfe8931e47b1461e20ee311142640e77145824c Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Wed, 1 May 2019 00:18:10 +0300 Subject: [PATCH 21/47] minor fix --- provider/keycloak_openid_client_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/keycloak_openid_client_test.go b/provider/keycloak_openid_client_test.go index 0748bd1a..14192aa0 100644 --- a/provider/keycloak_openid_client_test.go +++ b/provider/keycloak_openid_client_test.go @@ -502,7 +502,7 @@ resource "keycloak_openid_client" "client" { service_accounts_enabled = %t web_origins = %s } - `, openidClient.RealmId, openidClient.ClientId, openidClient.Name, openidClient.Enabled, openidClient.Description, openidClient.ClientSecret, openidClient.StandardFlowEnabled, openidClient.ImplicitFlowEnabled, openidClient.ServiceAccountsEnabled, openidClient.DirectAccessGrantsEnabled, arrayOfStringsForTerraformResource(openidClient.ValidRedirectUris), arrayOfStringsForTerraformResource(openidClient.WebOrigins)) + `, openidClient.RealmId, openidClient.ClientId, openidClient.Name, openidClient.Enabled, openidClient.Description, openidClient.ClientSecret, openidClient.StandardFlowEnabled, openidClient.ImplicitFlowEnabled, openidClient.ServiceAccountsEnabled, openidClient.DirectAccessGrantsEnabled, arrayOfStringsForTerraformResource(openidClient.WebOrigins)) } func testKeycloakOpenidClient_secret(realm, clientId, clientSecret string) string { From ed8a631c7a9c45f4ea20eee13f5e7e1b9fcc0625 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Wed, 1 May 2019 00:25:23 +0300 Subject: [PATCH 22/47] minor fix --- provider/keycloak_openid_client_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/provider/keycloak_openid_client_test.go b/provider/keycloak_openid_client_test.go index 14192aa0..86e4ad1e 100644 --- a/provider/keycloak_openid_client_test.go +++ b/provider/keycloak_openid_client_test.go @@ -129,6 +129,10 @@ func TestAccKeycloakOpenidClient_updateInPlace(t *testing.T) { directAccessGrantsEnabled := randomBool() serviceAccountsEnabled := randomBool() + if !standardFlowEnabled { + implicitFlowEnabled = !standardFlowEnabled + } + openidClientBefore := &keycloak.OpenidClient{ RealmId: realm, ClientId: clientId, @@ -500,9 +504,11 @@ resource "keycloak_openid_client" "client" { implicit_flow_enabled = %t direct_access_grants_enabled = %t service_accounts_enabled = %t + + valid_redirect_uris = %s web_origins = %s } - `, openidClient.RealmId, openidClient.ClientId, openidClient.Name, openidClient.Enabled, openidClient.Description, openidClient.ClientSecret, openidClient.StandardFlowEnabled, openidClient.ImplicitFlowEnabled, openidClient.ServiceAccountsEnabled, openidClient.DirectAccessGrantsEnabled, arrayOfStringsForTerraformResource(openidClient.WebOrigins)) + `, openidClient.RealmId, openidClient.ClientId, openidClient.Name, openidClient.Enabled, openidClient.Description, openidClient.ClientSecret, openidClient.StandardFlowEnabled, openidClient.ImplicitFlowEnabled, openidClient.ServiceAccountsEnabled, openidClient.DirectAccessGrantsEnabled, arrayOfStringsForTerraformResource(openidClient.ValidRedirectUris), arrayOfStringsForTerraformResource(openidClient.WebOrigins)) } func testKeycloakOpenidClient_secret(realm, clientId, clientSecret string) string { From 62d0e1b8e84a4ab0d5a0d2ab298d6480e74a2cb6 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Wed, 1 May 2019 00:37:56 +0300 Subject: [PATCH 23/47] minor fix --- provider/keycloak_openid_client_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/provider/keycloak_openid_client_test.go b/provider/keycloak_openid_client_test.go index 86e4ad1e..1beeb664 100644 --- a/provider/keycloak_openid_client_test.go +++ b/provider/keycloak_openid_client_test.go @@ -148,6 +148,8 @@ func TestAccKeycloakOpenidClient_updateInPlace(t *testing.T) { WebOrigins: []string{acctest.RandString(10), acctest.RandString(10), acctest.RandString(10)}, } + standardFlowEnabled, implicitFlowEnabled = implicitFlowEnabled, standardFlowEnabled + openidClientAfter := &keycloak.OpenidClient{ RealmId: realm, ClientId: clientId, @@ -155,8 +157,8 @@ func TestAccKeycloakOpenidClient_updateInPlace(t *testing.T) { Enabled: !enabled, Description: acctest.RandString(50), ClientSecret: acctest.RandString(10), - StandardFlowEnabled: !standardFlowEnabled, - ImplicitFlowEnabled: !implicitFlowEnabled, + StandardFlowEnabled: standardFlowEnabled, + ImplicitFlowEnabled: implicitFlowEnabled, DirectAccessGrantsEnabled: !directAccessGrantsEnabled, ServiceAccountsEnabled: !serviceAccountsEnabled, ValidRedirectUris: []string{acctest.RandString(10), acctest.RandString(10)}, From 49697d02796b1cebd9d2a6ebc8363fd7973c088c Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Wed, 1 May 2019 23:24:46 +0300 Subject: [PATCH 24/47] updated service account role logic --- example/main.tf | 5 ++- keycloak/openid_client.go | 44 +++++++------------ .../data_source_keycloak_openid_client.go | 16 ++++++- provider/keycloak_openid_client.go | 43 ++++++++++++++++-- ...loak_openid_client_service_account_role.go | 38 ++++++++-------- 5 files changed, 92 insertions(+), 54 deletions(-) diff --git a/example/main.tf b/example/main.tf index 353947ad..27eb9b86 100644 --- a/example/main.tf +++ b/example/main.tf @@ -465,6 +465,7 @@ resource "keycloak_openid_client" "test_client_auth" { access_type = "CONFIDENTIAL" direct_access_grants_enabled = true implicit_flow_enabled = true + service_accounts_enabled = true valid_redirect_uris = [ "http://localhost:5555/callback", @@ -513,7 +514,7 @@ resource "keycloak_user" "resource" { resource "keycloak_openid_client_service_account_role" "read_token" { realm_id = "${keycloak_realm.test.id}" - source_client_id = "${data.keycloak_openid_client.broker.id}" - target_client_id = "${keycloak_openid_client.test_client_auth.id}" + client_id = "${data.keycloak_openid_client.broker.id}" + service_account_user_id = "${keycloak_openid_client.test_client_auth.service_account_user_id}" role = "read-token" } diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 803746d1..cafe521e 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -69,13 +69,13 @@ type OpenidClientAuthorizationPolicy struct { } type OpenidClientServiceAccountRole struct { - Id string `json:"id"` - RealmId string `json:"-"` - ClientId string `json:"-"` - Name string `json:"name"` - ClientRole bool `json:"clientRole"` - Composite bool `json:"composite"` - ContainerId string `json:"containerId"` + Id string `json:"id"` + RealmId string `json:"-"` + ServiceAccountUserId string `json:"-"` + Name string `json:"name"` + ClientRole bool `json:"clientRole"` + Composite bool `json:"composite"` + ContainerId string `json:"containerId"` } type OpenidClientAuthorizationSettings struct { @@ -199,10 +199,6 @@ func (keycloakClient *KeycloakClient) GetClientByName(realm, clientId string) (* } func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceAccountRole *OpenidClientServiceAccountRole) error { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(serviceAccountRole.RealmId, serviceAccountRole.ClientId) - if err != nil { - return err - } role, err := keycloakClient.GetClientRoleByName(serviceAccountRole.RealmId, serviceAccountRole.ContainerId, serviceAccountRole.Name) if err != nil { return err @@ -210,42 +206,34 @@ func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceA serviceAccountRole.Id = role.Id serviceAccountRoles := []OpenidClientServiceAccountRole{} serviceAccountRoles = append(serviceAccountRoles, *serviceAccountRole) - _, _, err = keycloakClient.post(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", serviceAccountRole.RealmId, serviceAccountUser.Id, serviceAccountRole.ContainerId), serviceAccountRoles) + _, _, err = keycloakClient.post(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.ContainerId), serviceAccountRoles) if err != nil { return err } return nil } -func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, sourceClientId, targetClientId, roleId string) error { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(realm, targetClientId) - if err != nil { - return err - } +func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) error { serviceAccountRoles := []OpenidClientServiceAccountRole{} serviceAccountRoles = append(serviceAccountRoles, OpenidClientServiceAccountRole{ Id: roleId, }) - err = keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUser.Id, sourceClientId), &serviceAccountRoles) + err := keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles) if err != nil { return err } return nil } -func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, sourceClientId, targetClientId, roleId string) (*OpenidClientServiceAccountRole, error) { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(realm, targetClientId) - if err != nil { - return nil, err - } +func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) (*OpenidClientServiceAccountRole, error) { serviceAccountRoles := []OpenidClientServiceAccountRole{} serviceAccountRoles = append(serviceAccountRoles, OpenidClientServiceAccountRole{ - Id: roleId, - RealmId: realm, - ContainerId: sourceClientId, - ClientId: targetClientId, + Id: roleId, + RealmId: realm, + ContainerId: clientId, + ServiceAccountUserId: serviceAccountUserId, }) - err = keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUser.Id, sourceClientId), &serviceAccountRoles, nil) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles, nil) if err != nil { return nil, err } diff --git a/provider/data_source_keycloak_openid_client.go b/provider/data_source_keycloak_openid_client.go index 2d141c7f..3277ea95 100644 --- a/provider/data_source_keycloak_openid_client.go +++ b/provider/data_source_keycloak_openid_client.go @@ -63,6 +63,10 @@ func dataSourceKeycloakOpenidClient() *schema.Resource { Set: schema.HashString, Computed: true, }, + "service_account_user_id": { + Type: schema.TypeString, + Computed: true, + }, "service_accounts_enabled": { Type: schema.TypeBool, Computed: true, @@ -99,7 +103,17 @@ func dataSourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interfac return handleNotFoundError(err, data) } - setOpenidClientData(data, client) + var serviceAccountUserId string + + if client.ServiceAccountsEnabled { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) + if err != nil { + return err + } + serviceAccountUserId = serviceAccountUser.Id + } + + setOpenidClientData(data, client, serviceAccountUserId) return nil } diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 7231f68c..be88f140 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -90,6 +90,10 @@ func resourceKeycloakOpenidClient() *schema.Resource { Optional: true, Default: false, }, + "service_account_user_id": { + Type: schema.TypeString, + Computed: true, + }, "authorization": { Type: schema.TypeSet, Optional: true, @@ -178,7 +182,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, return openidClient, nil } -func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient) { +func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, serviceAccountUserId string) { data.SetId(client.Id) data.Set("client_id", client.ClientId) @@ -194,6 +198,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien data.Set("valid_redirect_uris", client.ValidRedirectUris) data.Set("web_origins", client.WebOrigins) data.Set("authorization_services_enabled", client.AuthorizationServicesEnabled) + data.Set("service_account_user_id", serviceAccountUserId) // access type if client.PublicClient { @@ -223,7 +228,17 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - setOpenidClientData(data, client) + var serviceAccountUserId string + + if client.ServiceAccountsEnabled { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) + if err != nil { + return err + } + serviceAccountUserId = serviceAccountUser.Id + } + + setOpenidClientData(data, client, serviceAccountUserId) return resourceKeycloakOpenidClientRead(data, meta) } @@ -239,7 +254,17 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ return handleNotFoundError(err, data) } - setOpenidClientData(data, client) + var serviceAccountUserId string + + if client.ServiceAccountsEnabled { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) + if err != nil { + return err + } + serviceAccountUserId = serviceAccountUser.Id + } + + setOpenidClientData(data, client, serviceAccountUserId) return nil } @@ -262,7 +287,17 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac return err } - setOpenidClientData(data, client) + var serviceAccountUserId string + + if client.ServiceAccountsEnabled { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) + if err != nil { + return err + } + serviceAccountUserId = serviceAccountUser.Id + } + + setOpenidClientData(data, client, serviceAccountUserId) return nil } diff --git a/provider/keycloak_openid_client_service_account_role.go b/provider/keycloak_openid_client_service_account_role.go index 18aae503..3d70a3d3 100644 --- a/provider/keycloak_openid_client_service_account_role.go +++ b/provider/keycloak_openid_client_service_account_role.go @@ -17,9 +17,9 @@ func resourceKeycloakOpenidClientServiceAccountRole() *schema.Resource { State: resourceKeycloakOpenidClientServiceAccountRoleImport, }, Schema: map[string]*schema.Schema{ - "source_client_id": { + "service_account_user_id": { Type: schema.TypeString, - Optional: true, + Required: true, ForceNew: true, }, "realm_id": { @@ -27,7 +27,7 @@ func resourceKeycloakOpenidClientServiceAccountRole() *schema.Resource { Required: true, ForceNew: true, }, - "target_client_id": { + "client_id": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -43,19 +43,19 @@ func resourceKeycloakOpenidClientServiceAccountRole() *schema.Resource { func getOpenidClientServiceAccountRoleFromData(data *schema.ResourceData) *keycloak.OpenidClientServiceAccountRole { return &keycloak.OpenidClientServiceAccountRole{ - Id: data.Id(), - ContainerId: data.Get("source_client_id").(string), - Name: data.Get("role").(string), - RealmId: data.Get("realm_id").(string), - ClientId: data.Get("target_client_id").(string), + Id: data.Id(), + ContainerId: data.Get("client_id").(string), + Name: data.Get("role").(string), + RealmId: data.Get("realm_id").(string), + ServiceAccountUserId: data.Get("service_account_user_id").(string), } } func setOpenidClientServiceAccountRoleData(data *schema.ResourceData, serviceAccountRole *keycloak.OpenidClientServiceAccountRole) { data.SetId(serviceAccountRole.Id) data.Set("realm_id", serviceAccountRole.RealmId) - data.Set("source_client_id", serviceAccountRole.ContainerId) - data.Set("target_client_id", serviceAccountRole.ClientId) + data.Set("client_id", serviceAccountRole.ContainerId) + data.Set("service_account_user_id", serviceAccountRole.ServiceAccountUserId) data.Set("role", serviceAccountRole.Name) } @@ -74,11 +74,11 @@ func resourceKeycloakOpenidClientServiceAccountRoleRead(data *schema.ResourceDat keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - sourceClientId := data.Get("source_client_id").(string) - targetClientId := data.Get("target_client_id").(string) + serviceAccountUserId := data.Get("service_account_user_id").(string) + clientId := data.Get("client_id").(string) id := data.Id() - serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, sourceClientId, targetClientId, id) + serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id) if err != nil { return handleNotFoundError(err, data) } @@ -92,21 +92,21 @@ func resourceKeycloakOpenidClientServiceAccountRoleDelete(data *schema.ResourceD keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - sourceClientId := data.Get("source_client_id").(string) - targetClientId := data.Get("target_client_id").(string) + serviceAccountUserId := data.Get("service_account_user_id").(string) + clientId := data.Get("client_id").(string) id := data.Id() - return keycloakClient.DeleteOpenidClientServiceAccountRole(realmId, sourceClientId, targetClientId, id) + return keycloakClient.DeleteOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id) } func resourceKeycloakOpenidClientServiceAccountRoleImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { parts := strings.Split(d.Id(), "/") if len(parts) != 3 { - return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{sourceClientId}}/{{targetClientId}}/{{role}}") + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{serviceAccountUserId}}/{{clientId}}/{{role}}") } d.Set("realm_id", parts[0]) - d.Set("source_client_id", parts[1]) - d.Set("target_client_id", parts[2]) + d.Set("service_account_user_id", parts[1]) + d.Set("client_id", parts[2]) d.SetId(parts[3]) return []*schema.ResourceData{d}, nil From 3f5ec97710ec3cee4fc4121aa3406edb512fdfed Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Thu, 2 May 2019 10:56:30 +0300 Subject: [PATCH 25/47] added resource_server_id --- keycloak/openid_client.go | 74 +++++++++---------- .../data_source_keycloak_openid_client.go | 4 + ...loak_openid_client_authorization_policy.go | 8 +- provider/keycloak_openid_client.go | 13 +++- ..._openid_client_authorization_permission.go | 20 ++--- ...ak_openid_client_authorization_resource.go | 20 ++--- ...cloak_openid_client_authorization_scope.go | 30 ++++---- 7 files changed, 92 insertions(+), 77 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index cafe521e..e1205f84 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -20,7 +20,7 @@ type OpenidClientSecret struct { } type OpenidClientAuthorizationResource struct { - ClientId string `json:"-"` + ResourceServerId string `json:"-"` RealmId string `json:"-"` Id string `json:"_id,omitempty"` DisplayName string `json:"displayName"` @@ -34,18 +34,18 @@ type OpenidClientAuthorizationResource struct { } type OpenidClientAuthorizationScope struct { - Id string `json:"id,omitempty"` - RealmId string `json:"-"` - ClientId string `json:"-"` - Name string `json:"name"` - DisplayName string `json:"displayName"` - IconUri string `json:"iconUri"` + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ResourceServerId string `json:"-"` + Name string `json:"name"` + DisplayName string `json:"displayName"` + IconUri string `json:"iconUri"` } type OpenidClientAuthorizationPermission struct { Id string `json:"id,omitempty"` RealmId string `json:"-"` - ClientId string `json:"-"` + ResourceServerId string `json:"-"` Name string `json:"name"` Description string `json:"description"` DecisionStrategy string `json:"decisionStrategy"` @@ -57,7 +57,7 @@ type OpenidClientAuthorizationPermission struct { type OpenidClientAuthorizationPolicy struct { Id string `json:"id,omitempty"` RealmId string `json:"-"` - ClientId string `json:"-"` + ResourceServerId string `json:"-"` Name string `json:"name"` Owner string `json:"owner"` DecisionStrategy string `json:"decisionStrategy"` @@ -105,41 +105,41 @@ type OpenidClient struct { AuthorizationSettings *OpenidClientAuthorizationSettings `json:"authorizationSettings,omitempty"` } -func (keycloakClient *KeycloakClient) GetClientAuthorizationPolicyByName(realmId, clientId, name string) (*OpenidClientAuthorizationPolicy, error) { +func (keycloakClient *KeycloakClient) GetClientAuthorizationPolicyByName(realmId, resourceServerId, name string) (*OpenidClientAuthorizationPolicy, error) { policies := []OpenidClientAuthorizationPolicy{} params := map[string]string{"name": name} - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy", realmId, clientId), &policies, params) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy", realmId, resourceServerId), &policies, params) if err != nil { return nil, err } policy := policies[0] policy.RealmId = realmId - policy.ClientId = clientId + policy.ResourceServerId = resourceServerId policy.Name = name return &policy, nil } -func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(realm, clientId, id string) (*OpenidClientAuthorizationPermission, error) { +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(realm, resourceServerId, id string) (*OpenidClientAuthorizationPermission, error) { permission := OpenidClientAuthorizationPermission{ - RealmId: realm, - ClientId: clientId, - Id: id, + RealmId: realm, + ResourceServerId: resourceServerId, + Id: id, } policies := []OpenidClientAuthorizationPolicy{} resources := []OpenidClientAuthorizationResource{} - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, clientId, id), &permission, nil) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, resourceServerId, id), &permission, nil) if err != nil { return nil, err } - err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/%s/associatedPolicies", realm, clientId, id), &policies, nil) + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/%s/associatedPolicies", realm, resourceServerId, id), &policies, nil) if err != nil { return nil, err } - err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s/resources", realm, clientId, id), &resources, nil) + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s/resources", realm, resourceServerId, id), &resources, nil) if err != nil { return nil, err } @@ -156,7 +156,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(rea } func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission", permission.RealmId, permission.ClientId), permission) + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission", permission.RealmId, permission.ResourceServerId), permission) if err != nil { return err } @@ -168,15 +168,15 @@ func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(per } func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ClientId, permission.Id), permission) + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ResourceServerId, permission.Id), permission) if err != nil { return err } return nil } -func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationPermission(realmId, clientId, permissionId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realmId, clientId, permissionId), nil) +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationPermission(realmId, resourceServerId, permissionId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realmId, resourceServerId, permissionId), nil) } func (keycloakClient *KeycloakClient) GetClientRoleByName(realm, clientId, name string) (*OpenidClientRole, error) { @@ -246,7 +246,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, s } func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", resource.RealmId, resource.ClientId), resource) + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", resource.RealmId, resource.ResourceServerId), resource) if err != nil { return err } @@ -257,12 +257,12 @@ func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationResource(resou return nil } -func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm, clientId, resourceId string) (*OpenidClientAuthorizationResource, error) { +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm, resourceServerId, resourceId string) (*OpenidClientAuthorizationResource, error) { resource := OpenidClientAuthorizationResource{ - RealmId: realm, - ClientId: clientId, + RealmId: realm, + ResourceServerId: resourceServerId, } - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, clientId, resourceId), &resource, nil) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, resourceServerId, resourceId), &resource, nil) if err != nil { return nil, err } @@ -270,7 +270,7 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm } func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", resource.RealmId, resource.ClientId, resource.Id), resource) + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", resource.RealmId, resource.ResourceServerId, resource.Id), resource) if err != nil { return err } @@ -282,7 +282,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationResource(re } func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope", scope.RealmId, scope.ClientId), scope) + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope", scope.RealmId, scope.ResourceServerId), scope) if err != nil { return err } @@ -293,12 +293,12 @@ func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationScope(scope *O return nil } -func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationScope(realm, clientId, scopeId string) (*OpenidClientAuthorizationScope, error) { +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationScope(realm, resourceServerId, scopeId string) (*OpenidClientAuthorizationScope, error) { scope := OpenidClientAuthorizationScope{ - RealmId: realm, - ClientId: clientId, + RealmId: realm, + ResourceServerId: resourceServerId, } - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realm, clientId, scopeId), &scope, nil) + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realm, resourceServerId, scopeId), &scope, nil) if err != nil { return nil, err } @@ -306,15 +306,15 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationScope(realm, c } func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", scope.RealmId, scope.ClientId, scope.Id), scope) + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", scope.RealmId, scope.ResourceServerId, scope.Id), scope) if err != nil { return err } return nil } -func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationScope(realmId, clientId, scopeId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realmId, clientId, scopeId), nil) +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationScope(realmId, resourceServerId, scopeId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realmId, resourceServerId, scopeId), nil) } func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountUserId(realmId, clientId string) (*User, error) { diff --git a/provider/data_source_keycloak_openid_client.go b/provider/data_source_keycloak_openid_client.go index 3277ea95..6d6b4b30 100644 --- a/provider/data_source_keycloak_openid_client.go +++ b/provider/data_source_keycloak_openid_client.go @@ -71,6 +71,10 @@ func dataSourceKeycloakOpenidClient() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "resource_server_id": { + Type: schema.TypeString, + Computed: true, + }, "authorization": { Type: schema.TypeSet, Computed: true, diff --git a/provider/data_source_keycloak_openid_client_authorization_policy.go b/provider/data_source_keycloak_openid_client_authorization_policy.go index 1eba98ee..29967e2e 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy.go @@ -10,7 +10,7 @@ func dataSourceKeycloakOpenidClientAuthorizationPolicy() *schema.Resource { Read: dataSourceKeycloakOpenidClientAuthorizationPolicyRead, Schema: map[string]*schema.Schema{ - "client_id": { + "resource_server_id": { Type: schema.TypeString, Required: true, }, @@ -60,7 +60,7 @@ func dataSourceKeycloakOpenidClientAuthorizationPolicy() *schema.Resource { func setOpenidClientAuthorizationPolicyData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationPolicy) { data.SetId(policy.Id) - data.Set("client_id", policy.ClientId) + data.Set("resource_server_id", policy.ResourceServerId) data.Set("realm_id", policy.RealmId) data.Set("name", policy.Name) data.Set("decision_strategy", policy.DecisionStrategy) @@ -76,10 +76,10 @@ func dataSourceKeycloakOpenidClientAuthorizationPolicyRead(data *schema.Resource keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) name := data.Get("name").(string) - client, err := keycloakClient.GetClientAuthorizationPolicyByName(realmId, clientId, name) + client, err := keycloakClient.GetClientAuthorizationPolicyByName(realmId, resourceServerId, name) if err != nil { return handleNotFoundError(err, data) } diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index be88f140..6ecfafa3 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -94,6 +94,10 @@ func resourceKeycloakOpenidClient() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "resource_server_id": { + Type: schema.TypeString, + Computed: true, + }, "authorization": { Type: schema.TypeSet, Optional: true, @@ -198,7 +202,14 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien data.Set("valid_redirect_uris", client.ValidRedirectUris) data.Set("web_origins", client.WebOrigins) data.Set("authorization_services_enabled", client.AuthorizationServicesEnabled) - data.Set("service_account_user_id", serviceAccountUserId) + + if client.AuthorizationServicesEnabled { + data.Set("resource_server_id", client.ClientId) + } + + if client.ServiceAccountsEnabled { + data.Set("service_account_user_id", serviceAccountUserId) + } // access type if client.PublicClient { diff --git a/provider/keycloak_openid_client_authorization_permission.go b/provider/keycloak_openid_client_authorization_permission.go index 88d09aed..4df92a5f 100644 --- a/provider/keycloak_openid_client_authorization_permission.go +++ b/provider/keycloak_openid_client_authorization_permission.go @@ -19,12 +19,12 @@ func resourceKeycloakOpenidClientAuthorizationPermission() *schema.Resource { Read: resourceKeycloakOpenidClientAuthorizationPermissionRead, Delete: resourceKeycloakOpenidClientAuthorizationPermissionDelete, Update: resourceKeycloakOpenidClientAuthorizationPermissionUpdate, - // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + // This resource can be imported using {{realm}}/{{resource_server_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientAuthorizationPermissionImport, }, Schema: map[string]*schema.Schema{ - "client_id": { + "resource_server_id": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -83,7 +83,7 @@ func getOpenidClientAuthorizationPermissionFromData(data *schema.ResourceData) * } permission := keycloak.OpenidClientAuthorizationPermission{ Id: data.Id(), - ClientId: data.Get("client_id").(string), + ResourceServerId: data.Get("resource_server_id").(string), RealmId: data.Get("realm_id").(string), Description: data.Get("description").(string), Name: data.Get("name").(string), @@ -97,7 +97,7 @@ func getOpenidClientAuthorizationPermissionFromData(data *schema.ResourceData) * func setOpenidClientAuthorizationPermissionData(data *schema.ResourceData, permission *keycloak.OpenidClientAuthorizationPermission) { data.SetId(permission.Id) - data.Set("client_id", permission.ClientId) + data.Set("resource_server_id", permission.ResourceServerId) data.Set("realm_id", permission.RealmId) data.Set("description", permission.Description) data.Set("name", permission.Name) @@ -126,10 +126,10 @@ func resourceKeycloakOpenidClientAuthorizationPermissionRead(data *schema.Resour keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) id := data.Id() - permission, err := keycloakClient.GetOpenidClientAuthorizationPermission(realmId, clientId, id) + permission, err := keycloakClient.GetOpenidClientAuthorizationPermission(realmId, resourceServerId, id) if err != nil { return handleNotFoundError(err, data) } @@ -158,19 +158,19 @@ func resourceKeycloakOpenidClientAuthorizationPermissionDelete(data *schema.Reso keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) id := data.Id() - return keycloakClient.DeleteOpenidClientAuthorizationPermission(realmId, clientId, id) + return keycloakClient.DeleteOpenidClientAuthorizationPermission(realmId, resourceServerId, id) } func resourceKeycloakOpenidClientAuthorizationPermissionImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { parts := strings.Split(d.Id(), "/") if len(parts) != 3 { - return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{clientId}}/{{permissionId}}") + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{resourceServerId}}/{{permissionId}}") } d.Set("realm_id", parts[0]) - d.Set("client_id", parts[1]) + d.Set("resource_server_id", parts[1]) d.SetId(parts[3]) return []*schema.ResourceData{d}, nil diff --git a/provider/keycloak_openid_client_authorization_resource.go b/provider/keycloak_openid_client_authorization_resource.go index c4bd4c7e..a5829b4e 100644 --- a/provider/keycloak_openid_client_authorization_resource.go +++ b/provider/keycloak_openid_client_authorization_resource.go @@ -13,12 +13,12 @@ func resourceKeycloakOpenidClientAuthorizationResource() *schema.Resource { Read: resourceKeycloakOpenidClientAuthorizationResourceRead, Delete: resourceKeycloakOpenidClientAuthorizationResourceDelete, Update: resourceKeycloakOpenidClientAuthorizationResourceUpdate, - // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + // This resource can be imported using {{realm}}/{{resource_server_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientAuthorizationResourceImport, }, Schema: map[string]*schema.Schema{ - "client_id": { + "resource_server_id": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -95,7 +95,7 @@ func getOpenidClientAuthorizationResourceFromData(data *schema.ResourceData) *ke IconUri: data.Get("icon_uri").(string), OwnerManagedAccess: data.Get("owner_managed_access").(bool), Type: data.Get("type").(string), - ClientId: data.Get("client_id").(string), + ResourceServerId: data.Get("resource_server_id").(string), RealmId: data.Get("realm_id").(string), Uris: uris, Scopes: scopes, @@ -110,7 +110,7 @@ func setOpenidClientAuthorizationResourceData(data *schema.ResourceData, resourc scopes = append(scopes, scope.Name) } data.SetId(resource.Id) - data.Set("client_id", resource.ClientId) + data.Set("resource_server_id", resource.ResourceServerId) data.Set("realm_id", resource.RealmId) data.Set("display_name", resource.DisplayName) data.Set("name", resource.Name) @@ -141,10 +141,10 @@ func resourceKeycloakOpenidClientAuthorizationResourceRead(data *schema.Resource keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) id := data.Id() - resource, err := keycloakClient.GetOpenidClientAuthorizationResource(realmId, clientId, id) + resource, err := keycloakClient.GetOpenidClientAuthorizationResource(realmId, resourceServerId, id) if err != nil { return handleNotFoundError(err, data) } @@ -173,19 +173,19 @@ func resourceKeycloakOpenidClientAuthorizationResourceDelete(data *schema.Resour keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) id := data.Id() - return keycloakClient.DeleteOpenidClientAuthorizationResource(realmId, clientId, id) + return keycloakClient.DeleteOpenidClientAuthorizationResource(realmId, resourceServerId, id) } func resourceKeycloakOpenidClientAuthorizationResourceImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { parts := strings.Split(d.Id(), "/") if len(parts) != 3 { - return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{clientId}}/{{authorizationResourceId}}") + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{resourceServerId}}/{{authorizationResourceId}}") } d.Set("realm_id", parts[0]) - d.Set("client_id", parts[1]) + d.Set("resource_server_id", parts[1]) d.SetId(parts[3]) return []*schema.ResourceData{d}, nil diff --git a/provider/keycloak_openid_client_authorization_scope.go b/provider/keycloak_openid_client_authorization_scope.go index 4fc8e92a..22475082 100644 --- a/provider/keycloak_openid_client_authorization_scope.go +++ b/provider/keycloak_openid_client_authorization_scope.go @@ -13,12 +13,12 @@ func resourceKeycloakOpenidClientAuthorizationScope() *schema.Resource { Read: resourceKeycloakOpenidClientAuthorizationScopeRead, Delete: resourceKeycloakOpenidClientAuthorizationScopeDelete, Update: resourceKeycloakOpenidClientAuthorizationScopeUpdate, - // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI + // This resource can be imported using {{realm}}/{{resource_server_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientAuthorizationScopeImport, }, Schema: map[string]*schema.Schema{ - "client_id": { + "resource_server_id": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -46,19 +46,19 @@ func resourceKeycloakOpenidClientAuthorizationScope() *schema.Resource { func getOpenidClientAuthorizationScopeFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationScope { scope := keycloak.OpenidClientAuthorizationScope{ - DisplayName: data.Get("display_name").(string), - Name: data.Get("name").(string), - IconUri: data.Get("icon_uri").(string), - Id: data.Id(), - ClientId: data.Get("client_id").(string), - RealmId: data.Get("realm_id").(string), + DisplayName: data.Get("display_name").(string), + Name: data.Get("name").(string), + IconUri: data.Get("icon_uri").(string), + Id: data.Id(), + ResourceServerId: data.Get("resource_server_id").(string), + RealmId: data.Get("realm_id").(string), } return &scope } func setOpenidClientAuthorizationScopeData(data *schema.ResourceData, scope *keycloak.OpenidClientAuthorizationScope) { data.SetId(scope.Id) - data.Set("client_id", scope.ClientId) + data.Set("resource_server_id", scope.ResourceServerId) data.Set("realm_id", scope.RealmId) data.Set("display_name", scope.DisplayName) data.Set("name", scope.Name) @@ -84,10 +84,10 @@ func resourceKeycloakOpenidClientAuthorizationScopeRead(data *schema.ResourceDat keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) id := data.Id() - scope, err := keycloakClient.GetOpenidClientAuthorizationScope(realmId, clientId, id) + scope, err := keycloakClient.GetOpenidClientAuthorizationScope(realmId, resourceServerId, id) if err != nil { return handleNotFoundError(err, data) } @@ -116,19 +116,19 @@ func resourceKeycloakOpenidClientAuthorizationScopeDelete(data *schema.ResourceD keycloakClient := meta.(*keycloak.KeycloakClient) realmId := data.Get("realm_id").(string) - clientId := data.Get("client_id").(string) + resourceServerId := data.Get("resource_server_id").(string) id := data.Id() - return keycloakClient.DeleteOpenidClientAuthorizationScope(realmId, clientId, id) + return keycloakClient.DeleteOpenidClientAuthorizationScope(realmId, resourceServerId, id) } func resourceKeycloakOpenidClientAuthorizationScopeImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { parts := strings.Split(d.Id(), "/") if len(parts) != 3 { - return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{clientId}}/{{authorizationScopeId}}") + return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{resourceServerId}}/{{authorizationScopeId}}") } d.Set("realm_id", parts[0]) - d.Set("client_id", parts[1]) + d.Set("resource_server_id", parts[1]) d.SetId(parts[3]) return []*schema.ResourceData{d}, nil From 4c1606c5a026091e1d4099123e358ba488ff0771 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Thu, 2 May 2019 11:02:47 +0300 Subject: [PATCH 26/47] updated examples --- example/main.tf | 47 ++++++++++++++++-------------- provider/keycloak_openid_client.go | 2 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/example/main.tf b/example/main.tf index 27eb9b86..7f043920 100644 --- a/example/main.tf +++ b/example/main.tf @@ -446,14 +446,14 @@ resource keycloak_hardcoded_attribute_identity_provider_mapper saml { } data "keycloak_openid_client" "broker" { - realm_id = "${keycloak_realm.test.id}" + realm_id = "${keycloak_realm.test.id}" client_id = "broker" } data "keycloak_openid_client_authorization_policy" "default" { - realm_id = "${keycloak_realm.test.id}" - client_id = "${keycloak_openid_client.test_client_auth.id}" - name = "default" + realm_id = "${keycloak_realm.test.id}" + resource_server_id = "${keycloak_openid_client.test_client_auth.resource_server_id}" + name = "default" } resource "keycloak_openid_client" "test_client_auth" { @@ -462,10 +462,10 @@ resource "keycloak_openid_client" "test_client_auth" { realm_id = "${keycloak_realm.test.id}" description = "a test openid client" - access_type = "CONFIDENTIAL" + access_type = "CONFIDENTIAL" direct_access_grants_enabled = true - implicit_flow_enabled = true - service_accounts_enabled = true + implicit_flow_enabled = true + service_accounts_enabled = true valid_redirect_uris = [ "http://localhost:5555/callback", @@ -479,42 +479,45 @@ resource "keycloak_openid_client" "test_client_auth" { } resource "keycloak_openid_client_authorization_permission" "resource" { - client_id = "${keycloak_openid_client.test_client_auth.id}" - realm_id = "${keycloak_realm.test.id}" - name = "test" - policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] - resources = ["${keycloak_openid_client_authorization_resource.resource.id}"] + resource_server_id = "${keycloak_openid_client.test_client_auth.resource_server_id}" + realm_id = "${keycloak_realm.test.id}" + name = "test" + policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] + resources = ["${keycloak_openid_client_authorization_resource.resource.id}"] } resource "keycloak_openid_client_authorization_resource" "resource" { - client_id = "${keycloak_openid_client.test_client_auth.id}" - name = "test-openid-client1" - realm_id = "${keycloak_realm.test.id}" + resource_server_id = "${keycloak_openid_client.test_client_auth.resource_server_id}" + name = "test-openid-client1" + realm_id = "${keycloak_realm.test.id}" + uris = [ - "/shit/*" + "/shit/*", ] + attributes = { "asdads" = "asdasd" } } resource "keycloak_openid_client_authorization_scope" "resource" { - client_id = "${keycloak_openid_client.test_client_auth.id}" - name = "test-openid-client1" - realm_id = "${keycloak_realm.test.id}" + resource_server_id = "${keycloak_openid_client.test_client_auth.resource_server_id}" + name = "test-openid-client1" + realm_id = "${keycloak_realm.test.id}" } resource "keycloak_user" "resource" { realm_id = "${keycloak_realm.test.id}" username = "test" + attributes = { "key" = "value" } } resource "keycloak_openid_client_service_account_role" "read_token" { - realm_id = "${keycloak_realm.test.id}" - client_id = "${data.keycloak_openid_client.broker.id}" + realm_id = "${keycloak_realm.test.id}" + client_id = "${data.keycloak_openid_client.broker.id}" service_account_user_id = "${keycloak_openid_client.test_client_auth.service_account_user_id}" - role = "read-token" + role = "read-token" } diff --git a/provider/keycloak_openid_client.go b/provider/keycloak_openid_client.go index 6ecfafa3..0343d2e9 100644 --- a/provider/keycloak_openid_client.go +++ b/provider/keycloak_openid_client.go @@ -204,7 +204,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien data.Set("authorization_services_enabled", client.AuthorizationServicesEnabled) if client.AuthorizationServicesEnabled { - data.Set("resource_server_id", client.ClientId) + data.Set("resource_server_id", client.Id) } if client.ServiceAccountsEnabled { From c5f739684c751e56a96e5c6e5a144bf93378672e Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Thu, 2 May 2019 11:06:51 +0300 Subject: [PATCH 27/47] minor fix --- example/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/main.tf b/example/main.tf index 27eb9b86..3f925419 100644 --- a/example/main.tf +++ b/example/main.tf @@ -491,7 +491,7 @@ resource "keycloak_openid_client_authorization_resource" "resource" { name = "test-openid-client1" realm_id = "${keycloak_realm.test.id}" uris = [ - "/shit/*" + "/endpoint/*" ] attributes = { "asdads" = "asdasd" From cdcd08afbc24a7806ad17ac680536ce1e689f013 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 08:26:25 +0300 Subject: [PATCH 28/47] renamed new providers, PR comments fixes --- keycloak/group.go | 7 +- keycloak/openid_client.go | 259 +----------------- .../openid_client_authorization_permission.go | 78 ++++++ .../openid_client_authorization_policy.go | 33 +++ .../openid_client_authorization_resource.go | 56 ++++ keycloak/openid_client_authorization_scope.go | 51 ++++ .../openid_client_service_account_role.go | 63 +++++ keycloak/user.go | 7 +- ...openid_client_authorization_permission.go} | 9 +- ...k_openid_client_authorization_resource.go} | 11 +- ...loak_openid_client_authorization_scope.go} | 1 - ...oak_openid_client_service_account_role.go} | 1 - 12 files changed, 305 insertions(+), 271 deletions(-) create mode 100644 keycloak/openid_client_authorization_permission.go create mode 100644 keycloak/openid_client_authorization_policy.go create mode 100644 keycloak/openid_client_authorization_resource.go create mode 100644 keycloak/openid_client_authorization_scope.go create mode 100644 keycloak/openid_client_service_account_role.go rename provider/{keycloak_openid_client_authorization_permission.go => resource_keycloak_openid_client_authorization_permission.go} (95%) rename provider/{keycloak_openid_client_authorization_resource.go => resource_keycloak_openid_client_authorization_resource.go} (95%) rename provider/{keycloak_openid_client_authorization_scope.go => resource_keycloak_openid_client_authorization_scope.go} (97%) rename provider/{keycloak_openid_client_service_account_role.go => resource_keycloak_openid_client_service_account_role.go} (97%) diff --git a/keycloak/group.go b/keycloak/group.go index 7766f02d..8418f303 100644 --- a/keycloak/group.go +++ b/keycloak/group.go @@ -2,7 +2,6 @@ package keycloak import ( "fmt" - "net/url" "strings" ) @@ -120,7 +119,11 @@ func (keycloakClient *KeycloakClient) DeleteGroup(realmId, id string) error { func (keycloakClient *KeycloakClient) ListGroupsWithName(realmId, name string) ([]*Group, error) { var groups []*Group - err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups?search=%s", realmId, url.QueryEscape(name)), &groups, nil) + params := map[string]string{ + "search": name, + } + + err := keycloakClient.get(fmt.Sprintf("/realms/%s/groups", realmId), &groups, params) if err != nil { return nil, err } diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index e1205f84..1e8b0006 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -1,7 +1,6 @@ package keycloak import ( - "encoding/json" "fmt" ) @@ -19,65 +18,6 @@ type OpenidClientSecret struct { Value string `json:"value"` } -type OpenidClientAuthorizationResource struct { - ResourceServerId string `json:"-"` - RealmId string `json:"-"` - Id string `json:"_id,omitempty"` - DisplayName string `json:"displayName"` - Name string `json:"name"` - Uris []string `json:"uris"` - IconUri string `json:"icon_uri"` - OwnerManagedAccess bool `json:"ownerManagedAccess"` - Scopes []OpenidClientAuthorizationScope `json:"scopes"` - Type string `json:"type"` - Attributes map[string][]string `json:"attributes"` -} - -type OpenidClientAuthorizationScope struct { - Id string `json:"id,omitempty"` - RealmId string `json:"-"` - ResourceServerId string `json:"-"` - Name string `json:"name"` - DisplayName string `json:"displayName"` - IconUri string `json:"iconUri"` -} - -type OpenidClientAuthorizationPermission struct { - Id string `json:"id,omitempty"` - RealmId string `json:"-"` - ResourceServerId string `json:"-"` - Name string `json:"name"` - Description string `json:"description"` - DecisionStrategy string `json:"decisionStrategy"` - Policies []string `json:"policies"` - Resources []string `json:"resources"` - Type string `json:"type"` -} - -type OpenidClientAuthorizationPolicy struct { - Id string `json:"id,omitempty"` - RealmId string `json:"-"` - ResourceServerId string `json:"-"` - Name string `json:"name"` - Owner string `json:"owner"` - DecisionStrategy string `json:"decisionStrategy"` - Logic string `json:"logic"` - Policies []string `json:"policies"` - Resources []string `json:"resources"` - Scopes []string `json:"scopes"` - Type string `json:"type"` -} - -type OpenidClientServiceAccountRole struct { - Id string `json:"id"` - RealmId string `json:"-"` - ServiceAccountUserId string `json:"-"` - Name string `json:"name"` - ClientRole bool `json:"clientRole"` - Composite bool `json:"composite"` - ContainerId string `json:"containerId"` -} - type OpenidClientAuthorizationSettings struct { PolicyEnforcementMode string `json:"policyEnforcementMode,omitempty"` AllowRemoteResourceManagement bool `json:"allowRemoteResourceManagement,omitempty"` @@ -105,80 +45,6 @@ type OpenidClient struct { AuthorizationSettings *OpenidClientAuthorizationSettings `json:"authorizationSettings,omitempty"` } -func (keycloakClient *KeycloakClient) GetClientAuthorizationPolicyByName(realmId, resourceServerId, name string) (*OpenidClientAuthorizationPolicy, error) { - policies := []OpenidClientAuthorizationPolicy{} - params := map[string]string{"name": name} - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy", realmId, resourceServerId), &policies, params) - if err != nil { - return nil, err - } - policy := policies[0] - policy.RealmId = realmId - policy.ResourceServerId = resourceServerId - policy.Name = name - return &policy, nil -} - -func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(realm, resourceServerId, id string) (*OpenidClientAuthorizationPermission, error) { - permission := OpenidClientAuthorizationPermission{ - RealmId: realm, - ResourceServerId: resourceServerId, - Id: id, - } - - policies := []OpenidClientAuthorizationPolicy{} - resources := []OpenidClientAuthorizationResource{} - - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, resourceServerId, id), &permission, nil) - if err != nil { - return nil, err - } - - err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/%s/associatedPolicies", realm, resourceServerId, id), &policies, nil) - if err != nil { - return nil, err - } - - err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s/resources", realm, resourceServerId, id), &resources, nil) - if err != nil { - return nil, err - } - - for _, policy := range policies { - permission.Policies = append(permission.Policies, policy.Id) - } - - for _, resource := range resources { - permission.Resources = append(permission.Resources, resource.Id) - } - - return &permission, nil -} - -func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission", permission.RealmId, permission.ResourceServerId), permission) - if err != nil { - return err - } - err = json.Unmarshal(body, &permission) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ResourceServerId, permission.Id), permission) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationPermission(realmId, resourceServerId, permissionId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realmId, resourceServerId, permissionId), nil) -} - func (keycloakClient *KeycloakClient) GetClientRoleByName(realm, clientId, name string) (*OpenidClientRole, error) { var clientRole OpenidClientRole err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/roles/%s", realm, clientId, name), &clientRole, nil) @@ -198,125 +64,6 @@ func (keycloakClient *KeycloakClient) GetClientByName(realm, clientId string) (* return &clients[0], nil } -func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceAccountRole *OpenidClientServiceAccountRole) error { - role, err := keycloakClient.GetClientRoleByName(serviceAccountRole.RealmId, serviceAccountRole.ContainerId, serviceAccountRole.Name) - if err != nil { - return err - } - serviceAccountRole.Id = role.Id - serviceAccountRoles := []OpenidClientServiceAccountRole{} - serviceAccountRoles = append(serviceAccountRoles, *serviceAccountRole) - _, _, err = keycloakClient.post(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.ContainerId), serviceAccountRoles) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) error { - serviceAccountRoles := []OpenidClientServiceAccountRole{} - serviceAccountRoles = append(serviceAccountRoles, OpenidClientServiceAccountRole{ - Id: roleId, - }) - err := keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) (*OpenidClientServiceAccountRole, error) { - serviceAccountRoles := []OpenidClientServiceAccountRole{} - serviceAccountRoles = append(serviceAccountRoles, OpenidClientServiceAccountRole{ - Id: roleId, - RealmId: realm, - ContainerId: clientId, - ServiceAccountUserId: serviceAccountUserId, - }) - err := keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles, nil) - if err != nil { - return nil, err - } - for _, serviceAccountRole := range serviceAccountRoles { - if serviceAccountRole.Id == roleId { - return &serviceAccountRole, nil - } - } - return nil, fmt.Errorf("No role with id %s found", roleId) -} - -func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", resource.RealmId, resource.ResourceServerId), resource) - if err != nil { - return err - } - err = json.Unmarshal(body, &resource) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm, resourceServerId, resourceId string) (*OpenidClientAuthorizationResource, error) { - resource := OpenidClientAuthorizationResource{ - RealmId: realm, - ResourceServerId: resourceServerId, - } - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, resourceServerId, resourceId), &resource, nil) - if err != nil { - return nil, err - } - return &resource, nil -} - -func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", resource.RealmId, resource.ResourceServerId, resource.Id), resource) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationResource(realmId, clientId, resourceId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realmId, clientId, resourceId), nil) -} - -func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { - body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope", scope.RealmId, scope.ResourceServerId), scope) - if err != nil { - return err - } - err = json.Unmarshal(body, &scope) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationScope(realm, resourceServerId, scopeId string) (*OpenidClientAuthorizationScope, error) { - scope := OpenidClientAuthorizationScope{ - RealmId: realm, - ResourceServerId: resourceServerId, - } - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realm, resourceServerId, scopeId), &scope, nil) - if err != nil { - return nil, err - } - return &scope, nil -} - -func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { - err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", scope.RealmId, scope.ResourceServerId, scope.Id), scope) - if err != nil { - return err - } - return nil -} - -func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationScope(realmId, resourceServerId, scopeId string) error { - return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realmId, resourceServerId, scopeId), nil) -} - func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountUserId(realmId, clientId string) (*User, error) { var serviceAccountUser User err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/service-account-user", realmId, clientId), &serviceAccountUser, nil) @@ -380,7 +127,11 @@ func (keycloakClient *KeycloakClient) GetOpenidClientByClientId(realmId, clientI var clients []OpenidClient var clientSecret OpenidClientSecret - err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients?clientId=%s", realmId, clientId), &clients, nil) + params := map[string]string{ + "clientId": clientId, + } + + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients", realmId), &clients, params) if err != nil { return nil, err } diff --git a/keycloak/openid_client_authorization_permission.go b/keycloak/openid_client_authorization_permission.go new file mode 100644 index 00000000..f8403b00 --- /dev/null +++ b/keycloak/openid_client_authorization_permission.go @@ -0,0 +1,78 @@ +package keycloak + +import ( + "encoding/json" + "fmt" +) + +type OpenidClientAuthorizationPermission struct { + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ResourceServerId string `json:"-"` + Name string `json:"name"` + Description string `json:"description"` + DecisionStrategy string `json:"decisionStrategy"` + Policies []string `json:"policies"` + Resources []string `json:"resources"` + Type string `json:"type"` +} + +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationPermission(realm, resourceServerId, id string) (*OpenidClientAuthorizationPermission, error) { + permission := OpenidClientAuthorizationPermission{ + RealmId: realm, + ResourceServerId: resourceServerId, + Id: id, + } + + policies := []OpenidClientAuthorizationPolicy{} + resources := []OpenidClientAuthorizationResource{} + + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", realm, resourceServerId, id), &permission, nil) + if err != nil { + return nil, err + } + + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/%s/associatedPolicies", realm, resourceServerId, id), &policies, nil) + if err != nil { + return nil, err + } + + err = keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s/resources", realm, resourceServerId, id), &resources, nil) + if err != nil { + return nil, err + } + + for _, policy := range policies { + permission.Policies = append(permission.Policies, policy.Id) + } + + for _, resource := range resources { + permission.Resources = append(permission.Resources, resource.Id) + } + + return &permission, nil +} + +func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission", permission.RealmId, permission.ResourceServerId), permission) + if err != nil { + return err + } + err = json.Unmarshal(body, &permission) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationPermission(permission *OpenidClientAuthorizationPermission) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/resource/%s", permission.RealmId, permission.ResourceServerId, permission.Id), permission) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationPermission(realmId, resourceServerId, permissionId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/permission/%s", realmId, resourceServerId, permissionId), nil) +} diff --git a/keycloak/openid_client_authorization_policy.go b/keycloak/openid_client_authorization_policy.go new file mode 100644 index 00000000..214fbbe0 --- /dev/null +++ b/keycloak/openid_client_authorization_policy.go @@ -0,0 +1,33 @@ +package keycloak + +import ( + "fmt" +) + +type OpenidClientAuthorizationPolicy struct { + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ResourceServerId string `json:"-"` + Name string `json:"name"` + Owner string `json:"owner"` + DecisionStrategy string `json:"decisionStrategy"` + Logic string `json:"logic"` + Policies []string `json:"policies"` + Resources []string `json:"resources"` + Scopes []string `json:"scopes"` + Type string `json:"type"` +} + +func (keycloakClient *KeycloakClient) GetClientAuthorizationPolicyByName(realmId, resourceServerId, name string) (*OpenidClientAuthorizationPolicy, error) { + policies := []OpenidClientAuthorizationPolicy{} + params := map[string]string{"name": name} + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy", realmId, resourceServerId), &policies, params) + if err != nil { + return nil, err + } + policy := policies[0] + policy.RealmId = realmId + policy.ResourceServerId = resourceServerId + policy.Name = name + return &policy, nil +} diff --git a/keycloak/openid_client_authorization_resource.go b/keycloak/openid_client_authorization_resource.go new file mode 100644 index 00000000..cd8a722e --- /dev/null +++ b/keycloak/openid_client_authorization_resource.go @@ -0,0 +1,56 @@ +package keycloak + +import ( + "encoding/json" + "fmt" +) + +type OpenidClientAuthorizationResource struct { + ResourceServerId string `json:"-"` + RealmId string `json:"-"` + Id string `json:"_id,omitempty"` + DisplayName string `json:"displayName"` + Name string `json:"name"` + Uris []string `json:"uris"` + IconUri string `json:"icon_uri"` + OwnerManagedAccess bool `json:"ownerManagedAccess"` + Scopes []OpenidClientAuthorizationScope `json:"scopes"` + Type string `json:"type"` + Attributes map[string][]string `json:"attributes"` +} + +func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", resource.RealmId, resource.ResourceServerId), resource) + if err != nil { + return err + } + err = json.Unmarshal(body, &resource) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm, resourceServerId, resourceId string) (*OpenidClientAuthorizationResource, error) { + resource := OpenidClientAuthorizationResource{ + RealmId: realm, + ResourceServerId: resourceServerId, + } + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realm, resourceServerId, resourceId), &resource, nil) + if err != nil { + return nil, err + } + return &resource, nil +} + +func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", resource.RealmId, resource.ResourceServerId, resource.Id), resource) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationResource(realmId, clientId, resourceId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", realmId, clientId, resourceId), nil) +} diff --git a/keycloak/openid_client_authorization_scope.go b/keycloak/openid_client_authorization_scope.go new file mode 100644 index 00000000..2490f70e --- /dev/null +++ b/keycloak/openid_client_authorization_scope.go @@ -0,0 +1,51 @@ +package keycloak + +import ( + "encoding/json" + "fmt" +) + +type OpenidClientAuthorizationScope struct { + Id string `json:"id,omitempty"` + RealmId string `json:"-"` + ResourceServerId string `json:"-"` + Name string `json:"name"` + DisplayName string `json:"displayName"` + IconUri string `json:"iconUri"` +} + +func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { + body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope", scope.RealmId, scope.ResourceServerId), scope) + if err != nil { + return err + } + err = json.Unmarshal(body, &scope) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationScope(realm, resourceServerId, scopeId string) (*OpenidClientAuthorizationScope, error) { + scope := OpenidClientAuthorizationScope{ + RealmId: realm, + ResourceServerId: resourceServerId, + } + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realm, resourceServerId, scopeId), &scope, nil) + if err != nil { + return nil, err + } + return &scope, nil +} + +func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationScope(scope *OpenidClientAuthorizationScope) error { + err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", scope.RealmId, scope.ResourceServerId, scope.Id), scope) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationScope(realmId, resourceServerId, scopeId string) error { + return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/scope/%s", realmId, resourceServerId, scopeId), nil) +} diff --git a/keycloak/openid_client_service_account_role.go b/keycloak/openid_client_service_account_role.go new file mode 100644 index 00000000..f595fdec --- /dev/null +++ b/keycloak/openid_client_service_account_role.go @@ -0,0 +1,63 @@ +package keycloak + +import ( + "fmt" +) + +type OpenidClientServiceAccountRole struct { + Id string `json:"id"` + RealmId string `json:"-"` + ServiceAccountUserId string `json:"-"` + Name string `json:"name"` + ClientRole bool `json:"clientRole"` + Composite bool `json:"composite"` + ContainerId string `json:"containerId"` +} + +func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceAccountRole *OpenidClientServiceAccountRole) error { + role, err := keycloakClient.GetClientRoleByName(serviceAccountRole.RealmId, serviceAccountRole.ContainerId, serviceAccountRole.Name) + if err != nil { + return err + } + serviceAccountRole.Id = role.Id + serviceAccountRoles := []OpenidClientServiceAccountRole{*serviceAccountRole} + _, _, err = keycloakClient.post(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.ContainerId), serviceAccountRoles) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) error { + serviceAccountRoles := []OpenidClientServiceAccountRole{ + OpenidClientServiceAccountRole{ + Id: roleId, + }, + } + err := keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles) + if err != nil { + return err + } + return nil +} + +func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) (*OpenidClientServiceAccountRole, error) { + serviceAccountRoles := []OpenidClientServiceAccountRole{ + OpenidClientServiceAccountRole{ + Id: roleId, + RealmId: realm, + ContainerId: clientId, + ServiceAccountUserId: serviceAccountUserId, + }, + } + err := keycloakClient.get(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles, nil) + if err != nil { + return nil, err + } + for _, serviceAccountRole := range serviceAccountRoles { + if serviceAccountRole.Id == roleId { + return &serviceAccountRole, nil + } + } + return nil, fmt.Errorf("No role with id %s found", roleId) +} diff --git a/keycloak/user.go b/keycloak/user.go index bb66b755..8dbd9ce7 100644 --- a/keycloak/user.go +++ b/keycloak/user.go @@ -2,7 +2,6 @@ package keycloak import ( "fmt" - "net/url" ) type FederatedIdentity struct { @@ -81,7 +80,11 @@ func (keycloakClient *KeycloakClient) DeleteUser(realmId, id string) error { func (keycloakClient *KeycloakClient) GetUserByUsername(realmId, username string) (*User, error) { var users []*User - err := keycloakClient.get(fmt.Sprintf("/realms/%s/users?username=%s", realmId, url.QueryEscape(username)), &users, nil) + params := map[string]string{ + "username": username, + } + + err := keycloakClient.get(fmt.Sprintf("/realms/%s/users", realmId), &users, params) if err != nil { return nil, err } diff --git a/provider/keycloak_openid_client_authorization_permission.go b/provider/resource_keycloak_openid_client_authorization_permission.go similarity index 95% rename from provider/keycloak_openid_client_authorization_permission.go rename to provider/resource_keycloak_openid_client_authorization_permission.go index 4df92a5f..0ce9f43a 100644 --- a/provider/keycloak_openid_client_authorization_permission.go +++ b/provider/resource_keycloak_openid_client_authorization_permission.go @@ -19,7 +19,6 @@ func resourceKeycloakOpenidClientAuthorizationPermission() *schema.Resource { Read: resourceKeycloakOpenidClientAuthorizationPermissionRead, Delete: resourceKeycloakOpenidClientAuthorizationPermissionDelete, Update: resourceKeycloakOpenidClientAuthorizationPermissionUpdate, - // This resource can be imported using {{realm}}/{{resource_server_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientAuthorizationPermissionImport, }, @@ -49,12 +48,12 @@ func resourceKeycloakOpenidClientAuthorizationPermission() *schema.Resource { Default: "UNANIMOUS", }, "policies": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, "resources": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, @@ -72,12 +71,12 @@ func getOpenidClientAuthorizationPermissionFromData(data *schema.ResourceData) * var policies []string var resources []string if v, ok := data.GetOk("resources"); ok { - for _, resource := range v.([]interface{}) { + for _, resource := range v.(*schema.Set).List() { resources = append(resources, resource.(string)) } } if v, ok := data.GetOk("policies"); ok { - for _, policy := range v.([]interface{}) { + for _, policy := range v.(*schema.Set).List() { policies = append(policies, policy.(string)) } } diff --git a/provider/keycloak_openid_client_authorization_resource.go b/provider/resource_keycloak_openid_client_authorization_resource.go similarity index 95% rename from provider/keycloak_openid_client_authorization_resource.go rename to provider/resource_keycloak_openid_client_authorization_resource.go index a5829b4e..e7aad5da 100644 --- a/provider/keycloak_openid_client_authorization_resource.go +++ b/provider/resource_keycloak_openid_client_authorization_resource.go @@ -13,7 +13,6 @@ func resourceKeycloakOpenidClientAuthorizationResource() *schema.Resource { Read: resourceKeycloakOpenidClientAuthorizationResourceRead, Delete: resourceKeycloakOpenidClientAuthorizationResourceDelete, Update: resourceKeycloakOpenidClientAuthorizationResourceUpdate, - // This resource can be imported using {{realm}}/{{resource_server_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientAuthorizationResourceImport, }, @@ -37,7 +36,7 @@ func resourceKeycloakOpenidClientAuthorizationResource() *schema.Resource { Optional: true, }, "uris": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, @@ -51,7 +50,7 @@ func resourceKeycloakOpenidClientAuthorizationResource() *schema.Resource { Default: false, }, "scopes": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, @@ -72,14 +71,14 @@ func getOpenidClientAuthorizationResourceFromData(data *schema.ResourceData) *ke var scopes []keycloak.OpenidClientAuthorizationScope attributes := map[string][]string{} if v, ok := data.GetOk("uris"); ok { - for _, uri := range v.([]interface{}) { + for _, uri := range v.(*schema.Set).List() { uris = append(uris, uri.(string)) } } if v, ok := data.GetOk("scopes"); ok { - for _, scope := range v.([]string) { + for _, scope := range v.(*schema.Set).List() { scopes = append(scopes, keycloak.OpenidClientAuthorizationScope{ - Name: scope, + Name: scope.(string), }) } } diff --git a/provider/keycloak_openid_client_authorization_scope.go b/provider/resource_keycloak_openid_client_authorization_scope.go similarity index 97% rename from provider/keycloak_openid_client_authorization_scope.go rename to provider/resource_keycloak_openid_client_authorization_scope.go index 22475082..723e29cf 100644 --- a/provider/keycloak_openid_client_authorization_scope.go +++ b/provider/resource_keycloak_openid_client_authorization_scope.go @@ -13,7 +13,6 @@ func resourceKeycloakOpenidClientAuthorizationScope() *schema.Resource { Read: resourceKeycloakOpenidClientAuthorizationScopeRead, Delete: resourceKeycloakOpenidClientAuthorizationScopeDelete, Update: resourceKeycloakOpenidClientAuthorizationScopeUpdate, - // This resource can be imported using {{realm}}/{{resource_server_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientAuthorizationScopeImport, }, diff --git a/provider/keycloak_openid_client_service_account_role.go b/provider/resource_keycloak_openid_client_service_account_role.go similarity index 97% rename from provider/keycloak_openid_client_service_account_role.go rename to provider/resource_keycloak_openid_client_service_account_role.go index 3d70a3d3..75be439f 100644 --- a/provider/keycloak_openid_client_service_account_role.go +++ b/provider/resource_keycloak_openid_client_service_account_role.go @@ -12,7 +12,6 @@ func resourceKeycloakOpenidClientServiceAccountRole() *schema.Resource { Create: resourceKeycloakOpenidClientServiceAccountRoleCreate, Read: resourceKeycloakOpenidClientServiceAccountRoleRead, Delete: resourceKeycloakOpenidClientServiceAccountRoleDelete, - // This resource can be imported using {{realm}}/{{client_id}}. The Client ID is displayed in the GUI Importer: &schema.ResourceImporter{ State: resourceKeycloakOpenidClientServiceAccountRoleImport, }, From eb3ea2a7207744bfa1de785c95c9353711ea3c6b Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 08:57:21 +0300 Subject: [PATCH 29/47] fmt fix --- keycloak/openid_client_service_account_role.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keycloak/openid_client_service_account_role.go b/keycloak/openid_client_service_account_role.go index f595fdec..ffd5b4a0 100644 --- a/keycloak/openid_client_service_account_role.go +++ b/keycloak/openid_client_service_account_role.go @@ -30,7 +30,7 @@ func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceA func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) error { serviceAccountRoles := []OpenidClientServiceAccountRole{ - OpenidClientServiceAccountRole{ + { Id: roleId, }, } @@ -43,7 +43,7 @@ func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) (*OpenidClientServiceAccountRole, error) { serviceAccountRoles := []OpenidClientServiceAccountRole{ - OpenidClientServiceAccountRole{ + { Id: roleId, RealmId: realm, ContainerId: clientId, From 484e7c28274fcf9968d8d8b97de1bdec8a7b205f Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 09:45:20 +0300 Subject: [PATCH 30/47] pr comments --- .../data_source_keycloak_openid_client.go | 13 ++--- provider/resource_keycloak_openid_client.go | 51 +++++++------------ ...cloak_openid_client_default_scopes_test.go | 1 - 3 files changed, 22 insertions(+), 43 deletions(-) diff --git a/provider/data_source_keycloak_openid_client.go b/provider/data_source_keycloak_openid_client.go index 6d6b4b30..8450c4b2 100644 --- a/provider/data_source_keycloak_openid_client.go +++ b/provider/data_source_keycloak_openid_client.go @@ -107,17 +107,10 @@ func dataSourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interfac return handleNotFoundError(err, data) } - var serviceAccountUserId string - - if client.ServiceAccountsEnabled { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) - if err != nil { - return err - } - serviceAccountUserId = serviceAccountUser.Id + err = setOpenidClientData(keycloakClient, data, client) + if err != nil { + return err } - setOpenidClientData(data, client, serviceAccountUserId) - return nil } diff --git a/provider/resource_keycloak_openid_client.go b/provider/resource_keycloak_openid_client.go index 0343d2e9..ee54c8a1 100644 --- a/provider/resource_keycloak_openid_client.go +++ b/provider/resource_keycloak_openid_client.go @@ -186,9 +186,16 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, return openidClient, nil } -func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClient, serviceAccountUserId string) { +func setOpenidClientData(keycloakClient *keycloak.KeycloakClient, data *schema.ResourceData, client *keycloak.OpenidClient) error { + var serviceAccountUserId string + if client.ServiceAccountsEnabled { + serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) + if err != nil { + return err + } + serviceAccountUserId = serviceAccountUser.Id + } data.SetId(client.Id) - data.Set("client_id", client.ClientId) data.Set("realm_id", client.RealmId) data.Set("name", client.Name) @@ -219,6 +226,7 @@ func setOpenidClientData(data *schema.ResourceData, client *keycloak.OpenidClien } else { data.Set("access_type", "CONFIDENTIAL") } + return nil } func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interface{}) error { @@ -239,18 +247,11 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac return err } - var serviceAccountUserId string - - if client.ServiceAccountsEnabled { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) - if err != nil { - return err - } - serviceAccountUserId = serviceAccountUser.Id + err = setOpenidClientData(keycloakClient, data, client) + if err != nil { + return err } - setOpenidClientData(data, client, serviceAccountUserId) - return resourceKeycloakOpenidClientRead(data, meta) } @@ -265,18 +266,11 @@ func resourceKeycloakOpenidClientRead(data *schema.ResourceData, meta interface{ return handleNotFoundError(err, data) } - var serviceAccountUserId string - - if client.ServiceAccountsEnabled { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) - if err != nil { - return err - } - serviceAccountUserId = serviceAccountUser.Id + err = setOpenidClientData(keycloakClient, data, client) + if err != nil { + return err } - setOpenidClientData(data, client, serviceAccountUserId) - return nil } @@ -298,18 +292,11 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac return err } - var serviceAccountUserId string - - if client.ServiceAccountsEnabled { - serviceAccountUser, err := keycloakClient.GetOpenidClientServiceAccountUserId(client.RealmId, client.Id) - if err != nil { - return err - } - serviceAccountUserId = serviceAccountUser.Id + err = setOpenidClientData(keycloakClient, data, client) + if err != nil { + return err } - setOpenidClientData(data, client, serviceAccountUserId) - return nil } diff --git a/provider/resource_keycloak_openid_client_default_scopes_test.go b/provider/resource_keycloak_openid_client_default_scopes_test.go index 2eb89582..9b1d63b6 100644 --- a/provider/resource_keycloak_openid_client_default_scopes_test.go +++ b/provider/resource_keycloak_openid_client_default_scopes_test.go @@ -595,7 +595,6 @@ resource "keycloak_openid_client_default_scopes" "default_scopes" { "email", "roles", "web-origins", - "microprofile-jwt", "${keycloak_openid_client_scope.client_scope.name}" ] } From 0084dd877521980ade658a9ce26f472ec3251114 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 14:16:25 +0300 Subject: [PATCH 31/47] added tests --- ...loak_openid_client_authorization_policy.go | 6 +- ...openid_client_authorization_policy_test.go | 71 +++++ ...data_source_keycloak_openid_client_test.go | 72 +++++ ...id_client_authorization_permission_test.go | 279 ++++++++++++++++++ ...enid_client_authorization_resource_test.go | 257 ++++++++++++++++ ..._openid_client_authorization_scope_test.go | 243 +++++++++++++++ ...openid_client_service_account_role_test.go | 186 ++++++++++++ 7 files changed, 1111 insertions(+), 3 deletions(-) create mode 100644 provider/data_source_keycloak_openid_client_authorization_policy_test.go create mode 100644 provider/data_source_keycloak_openid_client_test.go create mode 100644 provider/resource_keycloak_openid_client_authorization_permission_test.go create mode 100644 provider/resource_keycloak_openid_client_authorization_resource_test.go create mode 100644 provider/resource_keycloak_openid_client_authorization_scope_test.go create mode 100644 provider/resource_keycloak_openid_client_service_account_role_test.go diff --git a/provider/data_source_keycloak_openid_client_authorization_policy.go b/provider/data_source_keycloak_openid_client_authorization_policy.go index 29967e2e..4fb0622f 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy.go @@ -35,17 +35,17 @@ func dataSourceKeycloakOpenidClientAuthorizationPolicy() *schema.Resource { Computed: true, }, "policies": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, }, "resources": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, }, "scopes": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, }, diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go new file mode 100644 index 00000000..51ee55f0 --- /dev/null +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -0,0 +1,71 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T) { + realm := acctest.RandomWithPrefix("tf-acc-test") + clientId := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.keycloak_openid_client_authorization_policy.test" + resourceName := "keycloak_openid_client_authorization_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKeycloakOpenidClientAuthorizationPolicyConfig(realm, clientId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "resource_server_id", resourceName, "resource_server_id"), + resource.TestCheckResourceAttrPair(dataSourceName, "realm_id", resourceName, "realm_id"), + resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(dataSourceName, "decision_strategy", resourceName, "decision_strategy"), + resource.TestCheckResourceAttrPair(dataSourceName, "owner", resourceName, "owner"), + resource.TestCheckResourceAttrPair(dataSourceName, "logic", resourceName, "logic"), + resource.TestCheckResourceAttrPair(dataSourceName, "type", resourceName, "type"), + resource.TestCheckResourceAttrPair(dataSourceName, "policies", resourceName, "policies"), + resource.TestCheckResourceAttrPair(dataSourceName, "resources", resourceName, "resources"), + resource.TestCheckResourceAttrPair(dataSourceName, "scopes", resourceName, "scopes"), + ), + }, + }, + }) +} + +func testAccKeycloakOpenidClientAuthorizationPolicyConfig(realm, clientId string) string { + return fmt.Sprintf(` +resource keycloak_realm test { + realm = "%s" + enabled = true + display_name = "foo" + account_theme = "base" + access_code_lifespan = "30m" +} + +resource keycloak_openid_client test { + client_id = "%s" + name = "%s" + realm_id = "${keycloak_realm.test.id}" + description = "a test openid client" + standard_flow_enabled = true + access_type = "CONFIDENTIAL" + client_secret = "secret" + valid_redirect_uris = [ + "http://localhost:5555/callback", + ] + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +data keycloak_openid_client_authorization_policy test { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + realm_id = "${keycloak_realm.test.id}" + name = "Default Policy" +} +`, realm, clientId, clientId) +} diff --git a/provider/data_source_keycloak_openid_client_test.go b/provider/data_source_keycloak_openid_client_test.go new file mode 100644 index 00000000..fdb5904f --- /dev/null +++ b/provider/data_source_keycloak_openid_client_test.go @@ -0,0 +1,72 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccKeycloakDataSourceOpenidClient_basic(t *testing.T) { + realm := acctest.RandomWithPrefix("tf-acc-test") + clientId := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.keycloak_openid_client.test" + resourceName := "keycloak_openid_client.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccKeycloakOpenidClientConfig(realm, clientId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "client_id", resourceName, "client_id"), + resource.TestCheckResourceAttrPair(dataSourceName, "realm_id", resourceName, "realm_id"), + resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(dataSourceName, "enabled", resourceName, "enabled"), + resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"), + resource.TestCheckResourceAttrPair(dataSourceName, "access_type", resourceName, "access_type"), + resource.TestCheckResourceAttrPair(dataSourceName, "client_secret", resourceName, "client_secret"), + resource.TestCheckResourceAttrPair(dataSourceName, "standard_flow_enabled", resourceName, "standard_flow_enabled"), + resource.TestCheckResourceAttrPair(dataSourceName, "implicit_flow_enabled", resourceName, "implicit_flow_enabled"), + resource.TestCheckResourceAttrPair(dataSourceName, "direct_access_grants_enabled", resourceName, "direct_access_grants_enabled"), + resource.TestCheckResourceAttrPair(dataSourceName, "valid_redirect_uris", resourceName, "valid_redirect_uris"), + resource.TestCheckResourceAttrPair(dataSourceName, "web_origins", resourceName, "web_origins"), + resource.TestCheckResourceAttrPair(dataSourceName, "service_account_user_id", resourceName, "service_account_user_id"), + resource.TestCheckResourceAttrPair(dataSourceName, "service_accounts_enabled", resourceName, "service_accounts_enabled"), + resource.TestCheckResourceAttrPair(dataSourceName, "resource_server_id", resourceName, "resource_server_id"), + ), + }, + }, + }) +} + +func testAccKeycloakOpenidClientConfig(realm, clientId string) string { + return fmt.Sprintf(` +resource keycloak_realm test { + realm = "%s" + enabled = true + display_name = "foo" + account_theme = "base" + access_code_lifespan = "30m" +} + +resource keycloak_openid_client test { + name = "%s" + client_id = "%s" + realm_id = "${keycloak_realm.test.id}" + description = "a test openid client" + standard_flow_enabled = true + access_type = "CONFIDENTIAL" + valid_redirect_uris = [ + "http://localhost:5555/callback", + ] + client_secret = "secret" +} + +data keycloak_openid_client test { + client_id = "${keycloak_openid_client.test.client_id}" + realm_id = "${keycloak_realm.test.id}" +} +`, realm, clientId, clientId) +} diff --git a/provider/resource_keycloak_openid_client_authorization_permission_test.go b/provider/resource_keycloak_openid_client_authorization_permission_test.go new file mode 100644 index 00000000..08923bc3 --- /dev/null +++ b/provider/resource_keycloak_openid_client_authorization_permission_test.go @@ -0,0 +1,279 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "testing" +) + +func TestAccKeycloakOpenidClientAuthorizationPermission_basic(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + resourceName := "terraform-" + acctest.RandString(10) + permissionName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationPermissionDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationPermission_basic(realmName, clientId, resourceName, permissionName), + Check: testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationPermission_createAfterManualDestroy(t *testing.T) { + var authorizationPermission = &keycloak.OpenidClientAuthorizationPermission{} + + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + resourceName := "terraform-" + acctest.RandString(10) + permissionName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationPermissionDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationPermission_basic(realmName, clientId, resourceName, permissionName), + Check: testAccCheckKeycloakOpenidClientAuthorizationPermissionFetch("keycloak_openid_client_authorization_permission.test", authorizationPermission), + }, + { + PreConfig: func() { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + err := keycloakClient.DeleteOpenidClientAuthorizationPermission(authorizationPermission.RealmId, authorizationPermission.ResourceServerId, authorizationPermission.Id) + if err != nil { + t.Fatal(err) + } + }, + Config: testKeycloakOpenidClientAuthorizationPermission_basic(realmName, clientId, resourceName, permissionName), + Check: testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationPermission_basicUpdateRealm(t *testing.T) { + firstRealm := "terraform-" + acctest.RandString(10) + secondRealm := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + resourceName := "terraform-" + acctest.RandString(10) + permissionName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationPermissionDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationPermission_basic(firstRealm, clientId, resourceName, permissionName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_permission.test", "realm", firstRealm), + ), + }, + { + Config: testKeycloakOpenidClientAuthorizationPermission_basic(secondRealm, clientId, resourceName, permissionName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_permission.test", "realm", secondRealm), + ), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationPermission_basicUpdateAll(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + + firstAuthrorizationPermission := &keycloak.OpenidClientAuthorizationPermission{ + RealmId: realmName, + Name: acctest.RandString(10), + Description: acctest.RandString(10), + } + + secondAuthrorizationPermission := &keycloak.OpenidClientAuthorizationPermission{ + RealmId: realmName, + Name: acctest.RandString(10), + Description: acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationPermissionDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationPermission_basicFromInterface(clientId, firstAuthrorizationPermission, acctest.RandString(10)), + Check: testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), + }, + { + Config: testKeycloakOpenidClientAuthorizationPermission_basicFromInterface(clientId, secondAuthrorizationPermission, acctest.RandString(10)), + Check: testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), + }, + }, + }) +} + +func testAccCheckKeycloakOpenidClientAuthorizationPermissionExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, err := getKeycloakOpenidClientAuthorizationPermissionFromState(s, resourceName) + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckKeycloakOpenidClientAuthorizationPermissionFetch(resourceName string, mapper *keycloak.OpenidClientAuthorizationPermission) resource.TestCheckFunc { + return func(s *terraform.State) error { + fetchedMapper, err := getKeycloakOpenidClientAuthorizationPermissionFromState(s, resourceName) + if err != nil { + return err + } + + mapper.ResourceServerId = fetchedMapper.ResourceServerId + mapper.RealmId = fetchedMapper.RealmId + mapper.Id = fetchedMapper.Id + + return nil + } +} + +func testAccCheckKeycloakOpenidClientAuthorizationPermissionDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "keycloak_openid_client_authorization_permission" { + continue + } + + realmId := rs.Primary.Attributes["realm_id"] + resourceServerId := rs.Primary.Attributes["resource_server_id"] + id := rs.Primary.ID + + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + authorizationPermission, _ := keycloakClient.GetOpenidClientAuthorizationPermission(realmId, resourceServerId, id) + if authorizationPermission != nil { + return fmt.Errorf("test config with id %s still exists", id) + } + } + + return nil + } +} + +func getKeycloakOpenidClientAuthorizationPermissionFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationPermission, error) { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return nil, fmt.Errorf("resource not found: %s", resourceName) + } + + realmId := rs.Primary.Attributes["realm_id"] + resourceServerId := rs.Primary.Attributes["resource_server_id"] + id := rs.Primary.ID + + authorizationPermission, err := keycloakClient.GetOpenidClientAuthorizationPermission(realmId, resourceServerId, id) + if err != nil { + return nil, fmt.Errorf("error getting authorization permission config with id %s: %s", id, err) + } + + return authorizationPermission, nil +} + +func testKeycloakOpenidClientAuthorizationPermission_basic(realm, clientId, resourceName, permissionName string) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.realm.id}" + access_type = "PUBLIC" + service_accounts_enabled = true + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +data keycloak_openid_client_authorization_policy default { + realm_id = "${keycloak_realm.test.id}" + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "default" +} + +resource keycloak_openid_client_authorization_resource test { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "%s" + realm_id = "${keycloak_realm.test.id}" + + uris = [ + "/endpoint/*" + ] +} + +resource keycloak_openid_client_authorization_permission test { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + realm_id = "${keycloak_realm.realm.id}" + name = "%s" + policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] + resources = ["${keycloak_openid_client_authorization_resource.test.id}"] +} + `, realm, clientId, resourceName, permissionName) +} + +func testKeycloakOpenidClientAuthorizationPermission_basicFromInterface(clientId string, authorizationPermission *keycloak.OpenidClientAuthorizationPermission, resourceName string) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.realm.id}" + access_type = "PUBLIC" + service_accounts_enabled = true + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +data keycloak_openid_client_authorization_policy default { + realm_id = "${keycloak_realm.test.id}" + resource_server_id = "${keycloak_openid_client.test_client_auth.resource_server_id}" + name = "default" +} + +resource keycloak_openid_client_authorization_resource resource { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "%s" + realm_id = "${keycloak_realm.test.id}" + + uris = [ + "/endpoint/*" + ] +} + +resource keycloak_openid_client_authorization_permission test { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + realm_id = "${keycloak_realm.realm.id}" + name = "%s" + policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] + resources = ["${keycloak_openid_client_authorization_resource.resource.id}"] + description = "%s" +} + `, authorizationPermission.RealmId, clientId, resourceName, authorizationPermission.Name, authorizationPermission.Description) +} diff --git a/provider/resource_keycloak_openid_client_authorization_resource_test.go b/provider/resource_keycloak_openid_client_authorization_resource_test.go new file mode 100644 index 00000000..93590d7c --- /dev/null +++ b/provider/resource_keycloak_openid_client_authorization_resource_test.go @@ -0,0 +1,257 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "testing" +) + +func TestAccKeycloakOpenidClientAuthorizationResource_basic(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + resourceName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationResource_basic(realmName, clientId, resourceName), + Check: testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationResource_createAfterManualDestroy(t *testing.T) { + var authorizationResource = &keycloak.OpenidClientAuthorizationResource{} + + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + resourceName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationResource_basic(realmName, clientId, resourceName), + Check: testAccCheckKeycloakOpenidClientAuthorizationResourceFetch("keycloak_openid_client_authorization_resource.test", authorizationResource), + }, + { + PreConfig: func() { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + err := keycloakClient.DeleteOpenidClientAuthorizationResource(authorizationResource.RealmId, authorizationResource.ResourceServerId, authorizationResource.Id) + if err != nil { + t.Fatal(err) + } + }, + Config: testKeycloakOpenidClientAuthorizationResource_basic(realmName, clientId, resourceName), + Check: testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationResource_basicUpdateRealm(t *testing.T) { + firstRealm := "terraform-" + acctest.RandString(10) + secondRealm := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + resourceName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationResource_basic(firstRealm, clientId, resourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_resource.test", "realm", firstRealm), + ), + }, + { + Config: testKeycloakOpenidClientAuthorizationResource_basic(secondRealm, clientId, resourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_resource.test", "realm", secondRealm), + ), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationResource_basicUpdateAll(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + ownerManagedAccess := randomBool() + + firstAuthrorizationResource := &keycloak.OpenidClientAuthorizationResource{ + RealmId: realmName, + Name: acctest.RandString(10), + DisplayName: acctest.RandString(10), + IconUri: acctest.RandString(10), + Type: acctest.RandString(10), + OwnerManagedAccess: ownerManagedAccess, + } + + secondAuthrorizationResource := &keycloak.OpenidClientAuthorizationResource{ + RealmId: realmName, + Name: acctest.RandString(10), + DisplayName: acctest.RandString(10), + IconUri: acctest.RandString(10), + Type: acctest.RandString(10), + OwnerManagedAccess: !ownerManagedAccess, + } + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationResource_basicFromInterface(clientId, firstAuthrorizationResource), + Check: testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), + }, + { + Config: testKeycloakOpenidClientAuthorizationResource_basicFromInterface(clientId, secondAuthrorizationResource), + Check: testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), + }, + }, + }) +} + +func testAccCheckKeycloakOpenidClientAuthorizationResourceExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, err := getKeycloakOpenidClientAuthorizationResourceFromState(s, resourceName) + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckKeycloakOpenidClientAuthorizationResourceFetch(resourceName string, mapper *keycloak.OpenidClientAuthorizationResource) resource.TestCheckFunc { + return func(s *terraform.State) error { + fetchedMapper, err := getKeycloakOpenidClientAuthorizationResourceFromState(s, resourceName) + if err != nil { + return err + } + + mapper.ResourceServerId = fetchedMapper.ResourceServerId + mapper.RealmId = fetchedMapper.RealmId + mapper.Id = fetchedMapper.Id + + return nil + } +} + +func testAccCheckKeycloakOpenidClientAuthorizationResourceDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "keycloak_openid_client_authorization_resource" { + continue + } + + realmId := rs.Primary.Attributes["realm_id"] + resourceServerId := rs.Primary.Attributes["resource_server_id"] + id := rs.Primary.ID + + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + authorizationResource, _ := keycloakClient.GetOpenidClientAuthorizationResource(realmId, resourceServerId, id) + if authorizationResource != nil { + return fmt.Errorf("test config with id %s still exists", id) + } + } + + return nil + } +} + +func getKeycloakOpenidClientAuthorizationResourceFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationResource, error) { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return nil, fmt.Errorf("resource not found: %s", resourceName) + } + + realmId := rs.Primary.Attributes["realm_id"] + resourceServerId := rs.Primary.Attributes["resource_server_id"] + id := rs.Primary.ID + + authorizationResource, err := keycloakClient.GetOpenidClientAuthorizationResource(realmId, resourceServerId, id) + if err != nil { + return nil, fmt.Errorf("error getting authorization resource config with id %s: %s", id, err) + } + + return authorizationResource, nil +} + +func testKeycloakOpenidClientAuthorizationResource_basic(realm, clientId, resourceName string) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.test.id}" + access_type = "PUBLIC" + service_accounts_enabled = true + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +resource keycloak_openid_client_authorization_resource resource { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "%s" + realm_id = "${keycloak_realm.test.id}" + + uris = [ + "/endpoint/*" + ] +} + `, realm, clientId, resourceName) +} + +func testKeycloakOpenidClientAuthorizationResource_basicFromInterface(clientId string, authorizationResource *keycloak.OpenidClientAuthorizationResource) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.realm.id}" + access_type = "PUBLIC" + service_accounts_enabled = true + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +resource keycloak_openid_client_authorization_resource resource { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "%s" + realm_id = "${keycloak_realm.test.id}" + display_name = "%s" + icon_uri = "%s" + owner_managed_access = %t + type = "%s" + uris = [ + "/test/" + ] +} + `, authorizationResource.RealmId, clientId, authorizationResource.Name, authorizationResource.DisplayName, authorizationResource.IconUri, authorizationResource.OwnerManagedAccess, authorizationResource.Type) +} diff --git a/provider/resource_keycloak_openid_client_authorization_scope_test.go b/provider/resource_keycloak_openid_client_authorization_scope_test.go new file mode 100644 index 00000000..1151cc4d --- /dev/null +++ b/provider/resource_keycloak_openid_client_authorization_scope_test.go @@ -0,0 +1,243 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "testing" +) + +func TestAccKeycloakOpenidClientAuthorizationScope_basic(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + scopeName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationScopeDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationScope_basic(realmName, clientId, scopeName), + Check: testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationScope_createAfterManualDestroy(t *testing.T) { + var authorizationScope = &keycloak.OpenidClientAuthorizationScope{} + + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + scopeName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationScopeDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationScope_basic(realmName, clientId, scopeName), + Check: testAccCheckKeycloakOpenidClientAuthorizationScopeFetch("keycloak_openid_client_authorization_scope.test", authorizationScope), + }, + { + PreConfig: func() { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + err := keycloakClient.DeleteOpenidClientAuthorizationScope(authorizationScope.RealmId, authorizationScope.ResourceServerId, authorizationScope.Id) + if err != nil { + t.Fatal(err) + } + }, + Config: testKeycloakOpenidClientAuthorizationScope_basic(realmName, clientId, scopeName), + Check: testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationScope_basicUpdateRealm(t *testing.T) { + firstRealm := "terraform-" + acctest.RandString(10) + secondRealm := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + scopeName := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationScopeDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationScope_basic(firstRealm, clientId, scopeName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_scope.test", "realm", firstRealm), + ), + }, + { + Config: testKeycloakOpenidClientAuthorizationScope_basic(secondRealm, clientId, scopeName), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_scope.test", "realm", secondRealm), + ), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientAuthorizationScope_basicUpdateAll(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + + firstAuthrorizationScope := &keycloak.OpenidClientAuthorizationScope{ + RealmId: realmName, + Name: acctest.RandString(10), + DisplayName: acctest.RandString(10), + IconUri: acctest.RandString(10), + } + + secondAuthrorizationScope := &keycloak.OpenidClientAuthorizationScope{ + RealmId: realmName, + Name: acctest.RandString(10), + DisplayName: acctest.RandString(10), + IconUri: acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientAuthorizationScopeDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientAuthorizationScope_basicFromInterface(clientId, firstAuthrorizationScope), + Check: testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), + }, + { + Config: testKeycloakOpenidClientAuthorizationScope_basicFromInterface(clientId, secondAuthrorizationScope), + Check: testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), + }, + }, + }) +} + +func testAccCheckKeycloakOpenidClientAuthorizationScopeExists(scopeName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, err := getKeycloakOpenidClientAuthorizationScopeFromState(s, scopeName) + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckKeycloakOpenidClientAuthorizationScopeFetch(scopeName string, authorizationScope *keycloak.OpenidClientAuthorizationScope) resource.TestCheckFunc { + return func(s *terraform.State) error { + fetchedAuthorizationScope, err := getKeycloakOpenidClientAuthorizationScopeFromState(s, scopeName) + if err != nil { + return err + } + + authorizationScope.ResourceServerId = fetchedAuthorizationScope.ResourceServerId + authorizationScope.RealmId = fetchedAuthorizationScope.RealmId + authorizationScope.Id = fetchedAuthorizationScope.Id + + return nil + } +} + +func testAccCheckKeycloakOpenidClientAuthorizationScopeDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "keycloak_openid_client_authorization_scope" { + continue + } + + realmId := rs.Primary.Attributes["realm_id"] + resourceServerId := rs.Primary.Attributes["resource_server_id"] + id := rs.Primary.ID + + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + authorizationScope, _ := keycloakClient.GetOpenidClientAuthorizationScope(realmId, resourceServerId, id) + if authorizationScope != nil { + return fmt.Errorf("test config with id %s still exists", id) + } + } + + return nil + } +} + +func getKeycloakOpenidClientAuthorizationScopeFromState(s *terraform.State, scopeName string) (*keycloak.OpenidClientAuthorizationScope, error) { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + rs, ok := s.RootModule().Resources[scopeName] + if !ok { + return nil, fmt.Errorf("resource not found: %s", scopeName) + } + + realmId := rs.Primary.Attributes["realm_id"] + resourceServerId := rs.Primary.Attributes["resource_server_id"] + id := rs.Primary.ID + + authorizationScope, err := keycloakClient.GetOpenidClientAuthorizationScope(realmId, resourceServerId, id) + if err != nil { + return nil, fmt.Errorf("error getting authorization scope config with id %s: %s", id, err) + } + + return authorizationScope, nil +} + +func testKeycloakOpenidClientAuthorizationScope_basic(realm, clientId, scopeName string) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.realm.id}" + access_type = "PUBLIC" + service_accounts_enabled = true + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +resource keycloak_openid_client_authorization_scope test { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "%s" + realm_id = "${keycloak_realm.test.id}" +} + `, realm, clientId, scopeName) +} + +func testKeycloakOpenidClientAuthorizationScope_basicFromInterface(clientId string, authorizationScope *keycloak.OpenidClientAuthorizationScope) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.realm.id}" + access_type = "PUBLIC" + service_accounts_enabled = true + authorization { + policy_enforcement_mode = "ENFORCING" + } +} + +resource keycloak_openid_client_authorization_scope test { + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" + name = "%s" + realm_id = "${keycloak_realm.test.id}" + display_name = "%s" + icon_uri = "%s" +} + `, authorizationScope.RealmId, clientId, authorizationScope.Name, authorizationScope.DisplayName, authorizationScope.IconUri) +} diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go new file mode 100644 index 00000000..cc26cf0b --- /dev/null +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -0,0 +1,186 @@ +package provider + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/mrparkers/terraform-provider-keycloak/keycloak" + "testing" +) + +func TestAccKeycloakOpenidClientServiceAccountRole_basic(t *testing.T) { + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientServiceAccountRoleDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientServiceAccountRole_basic(realmName, clientId), + Check: testAccCheckKeycloakOpenidClientServiceAccountRoleExists("keycloak_openid_client_service_account_role.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientServiceAccountRole_createAfterManualDestroy(t *testing.T) { + var serviceAccountRole = &keycloak.OpenidClientServiceAccountRole{} + + realmName := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientServiceAccountRoleDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientServiceAccountRole_basic(realmName, clientId), + Check: testAccCheckKeycloakOpenidClientServiceAccountRoleFetch("keycloak_openid_client_service_account_role.test", serviceAccountRole), + }, + { + PreConfig: func() { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + err := keycloakClient.DeleteOpenidClientServiceAccountRole(serviceAccountRole.RealmId, serviceAccountRole.ServiceAccountUserId, serviceAccountRole.ContainerId, serviceAccountRole.Id) + if err != nil { + t.Fatal(err) + } + }, + Config: testKeycloakOpenidClientServiceAccountRole_basic(realmName, clientId), + Check: testAccCheckKeycloakOpenidClientServiceAccountRoleExists("keycloak_openid_client_service_account_role.test"), + }, + }, + }) +} + +func TestAccKeycloakOpenidClientServiceAccountRole_basicUpdateRealm(t *testing.T) { + firstRealm := "terraform-" + acctest.RandString(10) + secondRealm := "terraform-" + acctest.RandString(10) + clientId := "terraform-" + acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccCheckKeycloakOpenidClientServiceAccountRoleDestroy(), + Steps: []resource.TestStep{ + { + Config: testKeycloakOpenidClientServiceAccountRole_basic(firstRealm, clientId), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientServiceAccountRoleExists("keycloak_openid_client_service_account_role.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_service_account_role.test", "realm", firstRealm), + ), + }, + { + Config: testKeycloakOpenidClientServiceAccountRole_basic(secondRealm, clientId), + Check: resource.ComposeTestCheckFunc( + testAccCheckKeycloakOpenidClientServiceAccountRoleExists("keycloak_openid_client_service_account_role.test"), + resource.TestCheckResourceAttr("keycloak_openid_client_service_account_role.test", "realm", secondRealm), + ), + }, + }, + }) +} + +func testAccCheckKeycloakOpenidClientServiceAccountRoleExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, err := getKeycloakOpenidClientServiceAccountRoleFromState(s, resourceName) + if err != nil { + return err + } + + return nil + } +} + +func testAccCheckKeycloakOpenidClientServiceAccountRoleFetch(resourceName string, serviceAccountRole *keycloak.OpenidClientServiceAccountRole) resource.TestCheckFunc { + return func(s *terraform.State) error { + fetchedServiceAccountRole, err := getKeycloakOpenidClientServiceAccountRoleFromState(s, resourceName) + if err != nil { + return err + } + + serviceAccountRole.ServiceAccountUserId = fetchedServiceAccountRole.ServiceAccountUserId + serviceAccountRole.RealmId = fetchedServiceAccountRole.RealmId + serviceAccountRole.ClientRole = fetchedServiceAccountRole.ClientRole + serviceAccountRole.ContainerId = fetchedServiceAccountRole.ContainerId + serviceAccountRole.Id = fetchedServiceAccountRole.Id + + return nil + } +} + +func testAccCheckKeycloakOpenidClientServiceAccountRoleDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "keycloak_openid_client_service_account_role" { + continue + } + + realmId := rs.Primary.Attributes["realm_id"] + serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] + clientId := rs.Primary.Attributes["client_id"] + role := rs.Primary.Attributes["role"] + + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + serviceAccountRole, _ := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, role) + if serviceAccountRole != nil { + return fmt.Errorf("service account role exists") + } + } + + return nil + } +} + +func getKeycloakOpenidClientServiceAccountRoleFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientServiceAccountRole, error) { + keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return nil, fmt.Errorf("resource not found: %s", resourceName) + } + + realmId := rs.Primary.Attributes["realm_id"] + serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] + clientId := rs.Primary.Attributes["client_id"] + role := rs.Primary.Attributes["role"] + + serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, role) + if err != nil { + return nil, fmt.Errorf("error getting service account role mapping: %s", err) + } + + return serviceAccountRole, nil +} + +func testKeycloakOpenidClientServiceAccountRole_basic(realm, clientId string) string { + return fmt.Sprintf(` +resource keycloak_realm realm { + realm = "%s" +} + +resource keycloak_openid_client test { + client_id = "%s" + realm_id = "${keycloak_realm.realm.id}" + access_type = "PUBLIC" + service_accounts_enabled = true +} + +data keycloak_openid_client broker { + realm_id = "${keycloak_realm.test.id}" + client_id = "broker" +} + +resource keycloak_openid_client_service_account_role test { + service_account_user_id = "${keycloak_openid_client.test.service_account_user_id}" + realm_id = "${keycloak_realm.realm.id}" + client_id = "${data.keycloak_openid_client.broker.id}" + role = "read-token" +} + `, realm, clientId) +} From 13fa44267cee5d74170742ae536a6a582c95df30 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 14:29:24 +0300 Subject: [PATCH 32/47] minor fix --- ...ce_keycloak_openid_client_authorization_policy_test.go | 1 + ...eycloak_openid_client_authorization_permission_test.go | 6 +++--- ..._keycloak_openid_client_authorization_resource_test.go | 6 +++--- ...rce_keycloak_openid_client_authorization_scope_test.go | 8 ++++---- ...ce_keycloak_openid_client_service_account_role_test.go | 6 +++--- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 51ee55f0..0447a076 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -52,6 +52,7 @@ resource keycloak_openid_client test { realm_id = "${keycloak_realm.test.id}" description = "a test openid client" standard_flow_enabled = true + service_accounts_enabled = true access_type = "CONFIDENTIAL" client_secret = "secret" valid_redirect_uris = [ diff --git a/provider/resource_keycloak_openid_client_authorization_permission_test.go b/provider/resource_keycloak_openid_client_authorization_permission_test.go index 08923bc3..965cb99e 100644 --- a/provider/resource_keycloak_openid_client_authorization_permission_test.go +++ b/provider/resource_keycloak_openid_client_authorization_permission_test.go @@ -237,13 +237,13 @@ resource keycloak_openid_client_authorization_permission test { func testKeycloakOpenidClientAuthorizationPermission_basicFromInterface(clientId string, authorizationPermission *keycloak.OpenidClientAuthorizationPermission, resourceName string) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } resource keycloak_openid_client test { client_id = "%s" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" access_type = "PUBLIC" service_accounts_enabled = true authorization { @@ -269,7 +269,7 @@ resource keycloak_openid_client_authorization_resource resource { resource keycloak_openid_client_authorization_permission test { resource_server_id = "${keycloak_openid_client.test.resource_server_id}" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" name = "%s" policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] resources = ["${keycloak_openid_client_authorization_resource.resource.id}"] diff --git a/provider/resource_keycloak_openid_client_authorization_resource_test.go b/provider/resource_keycloak_openid_client_authorization_resource_test.go index 93590d7c..ae1dd409 100644 --- a/provider/resource_keycloak_openid_client_authorization_resource_test.go +++ b/provider/resource_keycloak_openid_client_authorization_resource_test.go @@ -199,7 +199,7 @@ func getKeycloakOpenidClientAuthorizationResourceFromState(s *terraform.State, r func testKeycloakOpenidClientAuthorizationResource_basic(realm, clientId, resourceName string) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } @@ -227,13 +227,13 @@ resource keycloak_openid_client_authorization_resource resource { func testKeycloakOpenidClientAuthorizationResource_basicFromInterface(clientId string, authorizationResource *keycloak.OpenidClientAuthorizationResource) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } resource keycloak_openid_client test { client_id = "%s" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" access_type = "PUBLIC" service_accounts_enabled = true authorization { diff --git a/provider/resource_keycloak_openid_client_authorization_scope_test.go b/provider/resource_keycloak_openid_client_authorization_scope_test.go index 1151cc4d..204c149b 100644 --- a/provider/resource_keycloak_openid_client_authorization_scope_test.go +++ b/provider/resource_keycloak_openid_client_authorization_scope_test.go @@ -194,13 +194,13 @@ func getKeycloakOpenidClientAuthorizationScopeFromState(s *terraform.State, scop func testKeycloakOpenidClientAuthorizationScope_basic(realm, clientId, scopeName string) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } resource keycloak_openid_client test { client_id = "%s" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" access_type = "PUBLIC" service_accounts_enabled = true authorization { @@ -218,13 +218,13 @@ resource keycloak_openid_client_authorization_scope test { func testKeycloakOpenidClientAuthorizationScope_basicFromInterface(clientId string, authorizationScope *keycloak.OpenidClientAuthorizationScope) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } resource keycloak_openid_client test { client_id = "%s" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" access_type = "PUBLIC" service_accounts_enabled = true authorization { diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index cc26cf0b..71ae182a 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -160,13 +160,13 @@ func getKeycloakOpenidClientServiceAccountRoleFromState(s *terraform.State, reso func testKeycloakOpenidClientServiceAccountRole_basic(realm, clientId string) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } resource keycloak_openid_client test { client_id = "%s" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" access_type = "PUBLIC" service_accounts_enabled = true } @@ -178,7 +178,7 @@ data keycloak_openid_client broker { resource keycloak_openid_client_service_account_role test { service_account_user_id = "${keycloak_openid_client.test.service_account_user_id}" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" client_id = "${data.keycloak_openid_client.broker.id}" role = "read-token" } From 51edd055349a84504091922c17c5f92e06f63e84 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 15:02:30 +0300 Subject: [PATCH 33/47] minor fix --- ..._keycloak_openid_client_authorization_permission_test.go | 6 +++--- ...ce_keycloak_openid_client_authorization_resource_test.go | 4 ++-- ...ource_keycloak_openid_client_authorization_scope_test.go | 4 ++-- ...urce_keycloak_openid_client_service_account_role_test.go | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/provider/resource_keycloak_openid_client_authorization_permission_test.go b/provider/resource_keycloak_openid_client_authorization_permission_test.go index 965cb99e..43a2c2b8 100644 --- a/provider/resource_keycloak_openid_client_authorization_permission_test.go +++ b/provider/resource_keycloak_openid_client_authorization_permission_test.go @@ -195,14 +195,14 @@ func getKeycloakOpenidClientAuthorizationPermissionFromState(s *terraform.State, func testKeycloakOpenidClientAuthorizationPermission_basic(realm, clientId, resourceName, permissionName string) string { return fmt.Sprintf(` -resource keycloak_realm realm { +resource keycloak_realm test { realm = "%s" } resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.realm.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { policy_enforcement_mode = "ENFORCING" @@ -244,7 +244,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.test.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { policy_enforcement_mode = "ENFORCING" diff --git a/provider/resource_keycloak_openid_client_authorization_resource_test.go b/provider/resource_keycloak_openid_client_authorization_resource_test.go index ae1dd409..fec23394 100644 --- a/provider/resource_keycloak_openid_client_authorization_resource_test.go +++ b/provider/resource_keycloak_openid_client_authorization_resource_test.go @@ -206,7 +206,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.test.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { policy_enforcement_mode = "ENFORCING" @@ -234,7 +234,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.test.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { policy_enforcement_mode = "ENFORCING" diff --git a/provider/resource_keycloak_openid_client_authorization_scope_test.go b/provider/resource_keycloak_openid_client_authorization_scope_test.go index 204c149b..4ee6bb45 100644 --- a/provider/resource_keycloak_openid_client_authorization_scope_test.go +++ b/provider/resource_keycloak_openid_client_authorization_scope_test.go @@ -201,7 +201,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.test.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { policy_enforcement_mode = "ENFORCING" @@ -225,7 +225,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.test.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { policy_enforcement_mode = "ENFORCING" diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index 71ae182a..e2a0b857 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -167,7 +167,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" realm_id = "${keycloak_realm.test.id}" - access_type = "PUBLIC" + access_type = "CONFIDENTIAL" service_accounts_enabled = true } From 5f7328c9f2327d7553df58507bfb6e6643312ad7 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 15:15:15 +0300 Subject: [PATCH 34/47] minor test fix --- ...loak_openid_client_authorization_permission_test.go | 10 +++++----- ...ycloak_openid_client_authorization_resource_test.go | 8 ++++---- ..._keycloak_openid_client_authorization_scope_test.go | 4 ++-- ...keycloak_openid_client_service_account_role_test.go | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/provider/resource_keycloak_openid_client_authorization_permission_test.go b/provider/resource_keycloak_openid_client_authorization_permission_test.go index 43a2c2b8..eaf373bd 100644 --- a/provider/resource_keycloak_openid_client_authorization_permission_test.go +++ b/provider/resource_keycloak_openid_client_authorization_permission_test.go @@ -77,14 +77,14 @@ func TestAccKeycloakOpenidClientAuthorizationPermission_basicUpdateRealm(t *test Config: testKeycloakOpenidClientAuthorizationPermission_basic(firstRealm, clientId, resourceName, permissionName), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_authorization_permission.test", "realm", firstRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_permission.test", "realm_id", firstRealm), ), }, { Config: testKeycloakOpenidClientAuthorizationPermission_basic(secondRealm, clientId, resourceName, permissionName), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientAuthorizationPermissionExists("keycloak_openid_client_authorization_permission.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_authorization_permission.test", "realm", secondRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_permission.test", "realm_id", secondRealm), ), }, }, @@ -201,7 +201,7 @@ resource keycloak_realm test { resource keycloak_openid_client test { client_id = "%s" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" access_type = "CONFIDENTIAL" service_accounts_enabled = true authorization { @@ -227,7 +227,7 @@ resource keycloak_openid_client_authorization_resource test { resource keycloak_openid_client_authorization_permission test { resource_server_id = "${keycloak_openid_client.test.resource_server_id}" - realm_id = "${keycloak_realm.realm.id}" + realm_id = "${keycloak_realm.test.id}" name = "%s" policies = ["${data.keycloak_openid_client_authorization_policy.default.id}"] resources = ["${keycloak_openid_client_authorization_resource.test.id}"] @@ -253,7 +253,7 @@ resource keycloak_openid_client test { data keycloak_openid_client_authorization_policy default { realm_id = "${keycloak_realm.test.id}" - resource_server_id = "${keycloak_openid_client.test_client_auth.resource_server_id}" + resource_server_id = "${keycloak_openid_client.test.resource_server_id}" name = "default" } diff --git a/provider/resource_keycloak_openid_client_authorization_resource_test.go b/provider/resource_keycloak_openid_client_authorization_resource_test.go index fec23394..7757cb23 100644 --- a/provider/resource_keycloak_openid_client_authorization_resource_test.go +++ b/provider/resource_keycloak_openid_client_authorization_resource_test.go @@ -74,14 +74,14 @@ func TestAccKeycloakOpenidClientAuthorizationResource_basicUpdateRealm(t *testin Config: testKeycloakOpenidClientAuthorizationResource_basic(firstRealm, clientId, resourceName), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_authorization_resource.test", "realm", firstRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_resource.test", "realm_id", firstRealm), ), }, { Config: testKeycloakOpenidClientAuthorizationResource_basic(secondRealm, clientId, resourceName), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientAuthorizationResourceExists("keycloak_openid_client_authorization_resource.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_authorization_resource.test", "realm", secondRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_resource.test", "realm_id", secondRealm), ), }, }, @@ -213,7 +213,7 @@ resource keycloak_openid_client test { } } -resource keycloak_openid_client_authorization_resource resource { +resource keycloak_openid_client_authorization_resource test { resource_server_id = "${keycloak_openid_client.test.resource_server_id}" name = "%s" realm_id = "${keycloak_realm.test.id}" @@ -241,7 +241,7 @@ resource keycloak_openid_client test { } } -resource keycloak_openid_client_authorization_resource resource { +resource keycloak_openid_client_authorization_resource test { resource_server_id = "${keycloak_openid_client.test.resource_server_id}" name = "%s" realm_id = "${keycloak_realm.test.id}" diff --git a/provider/resource_keycloak_openid_client_authorization_scope_test.go b/provider/resource_keycloak_openid_client_authorization_scope_test.go index 4ee6bb45..854322f7 100644 --- a/provider/resource_keycloak_openid_client_authorization_scope_test.go +++ b/provider/resource_keycloak_openid_client_authorization_scope_test.go @@ -74,14 +74,14 @@ func TestAccKeycloakOpenidClientAuthorizationScope_basicUpdateRealm(t *testing.T Config: testKeycloakOpenidClientAuthorizationScope_basic(firstRealm, clientId, scopeName), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_authorization_scope.test", "realm", firstRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_scope.test", "realm_id", firstRealm), ), }, { Config: testKeycloakOpenidClientAuthorizationScope_basic(secondRealm, clientId, scopeName), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientAuthorizationScopeExists("keycloak_openid_client_authorization_scope.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_authorization_scope.test", "realm", secondRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_authorization_scope.test", "realm_id", secondRealm), ), }, }, diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index e2a0b857..76eae656 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -71,14 +71,14 @@ func TestAccKeycloakOpenidClientServiceAccountRole_basicUpdateRealm(t *testing.T Config: testKeycloakOpenidClientServiceAccountRole_basic(firstRealm, clientId), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientServiceAccountRoleExists("keycloak_openid_client_service_account_role.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_service_account_role.test", "realm", firstRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_service_account_role.test", "realm_id", firstRealm), ), }, { Config: testKeycloakOpenidClientServiceAccountRole_basic(secondRealm, clientId), Check: resource.ComposeTestCheckFunc( testAccCheckKeycloakOpenidClientServiceAccountRoleExists("keycloak_openid_client_service_account_role.test"), - resource.TestCheckResourceAttr("keycloak_openid_client_service_account_role.test", "realm", secondRealm), + resource.TestCheckResourceAttr("keycloak_openid_client_service_account_role.test", "realm_id", secondRealm), ), }, }, From a1fd8bcdeaccc49e1581d221ffc127693be8ee22 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 15:28:28 +0300 Subject: [PATCH 35/47] fixed getclientbyName --- keycloak/openid_client.go | 3 +++ ..._source_keycloak_openid_client_authorization_policy_test.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 1e8b0006..fdfac7ad 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -61,6 +61,9 @@ func (keycloakClient *KeycloakClient) GetClientByName(realm, clientId string) (* if err != nil { return nil, err } + if len(clients) == 0 { + return nil, fmt.Errorf("no clients with name %s found", clientId) + } return &clients[0], nil } diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 0447a076..dfc80b6d 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -66,7 +66,7 @@ resource keycloak_openid_client test { data keycloak_openid_client_authorization_policy test { resource_server_id = "${keycloak_openid_client.test.resource_server_id}" realm_id = "${keycloak_realm.test.id}" - name = "Default Policy" + name = "default" } `, realm, clientId, clientId) } From 3cd9b3de5f29f0b0a1f34c725cf93271e07b3925 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 15:37:04 +0300 Subject: [PATCH 36/47] fixed delete request --- keycloak/keycloak_client.go | 2 +- keycloak/openid_client.go | 3 +++ ..._source_keycloak_openid_client_authorization_policy_test.go | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/keycloak/keycloak_client.go b/keycloak/keycloak_client.go index 41f22016..f131a97f 100644 --- a/keycloak/keycloak_client.go +++ b/keycloak/keycloak_client.go @@ -167,7 +167,7 @@ func (keycloakClient *KeycloakClient) addRequestHeaders(request *http.Request) { request.Header.Set("Authorization", fmt.Sprintf("%s %s", tokenType, accessToken)) request.Header.Set("Accept", "application/json") - if request.Method == http.MethodPost || request.Method == http.MethodPut { + if request.Method == http.MethodPost || request.Method == http.MethodPut || request.Method == http.MethodDelete { request.Header.Set("Content-type", "application/json") } } diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 1e8b0006..fdfac7ad 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -61,6 +61,9 @@ func (keycloakClient *KeycloakClient) GetClientByName(realm, clientId string) (* if err != nil { return nil, err } + if len(clients) == 0 { + return nil, fmt.Errorf("no clients with name %s found", clientId) + } return &clients[0], nil } diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 0447a076..dfc80b6d 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -66,7 +66,7 @@ resource keycloak_openid_client test { data keycloak_openid_client_authorization_policy test { resource_server_id = "${keycloak_openid_client.test.resource_server_id}" realm_id = "${keycloak_realm.test.id}" - name = "Default Policy" + name = "default" } `, realm, clientId, clientId) } From adf1a3b991c62ba26833c983e3bd6139f03512d3 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 16:34:50 +0300 Subject: [PATCH 37/47] fixed auth policy test --- keycloak/openid_client.go | 4 +++- ..._openid_client_authorization_policy_test.go | 18 +++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index fdfac7ad..6b47902c 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -64,7 +64,9 @@ func (keycloakClient *KeycloakClient) GetClientByName(realm, clientId string) (* if len(clients) == 0 { return nil, fmt.Errorf("no clients with name %s found", clientId) } - return &clients[0], nil + client := clients[0] + client.RealmId = realm + return &client, nil } func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountUserId(realmId, clientId string) (*User, error) { diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index dfc80b6d..54802ac2 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" + "regexp" "testing" ) @@ -11,7 +12,6 @@ func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T realm := acctest.RandomWithPrefix("tf-acc-test") clientId := acctest.RandomWithPrefix("tf-acc-test") dataSourceName := "data.keycloak_openid_client_authorization_policy.test" - resourceName := "keycloak_openid_client_authorization_policy.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -20,16 +20,12 @@ func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T { Config: testAccKeycloakOpenidClientAuthorizationPolicyConfig(realm, clientId), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrPair(dataSourceName, "resource_server_id", resourceName, "resource_server_id"), - resource.TestCheckResourceAttrPair(dataSourceName, "realm_id", resourceName, "realm_id"), - resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"), - resource.TestCheckResourceAttrPair(dataSourceName, "decision_strategy", resourceName, "decision_strategy"), - resource.TestCheckResourceAttrPair(dataSourceName, "owner", resourceName, "owner"), - resource.TestCheckResourceAttrPair(dataSourceName, "logic", resourceName, "logic"), - resource.TestCheckResourceAttrPair(dataSourceName, "type", resourceName, "type"), - resource.TestCheckResourceAttrPair(dataSourceName, "policies", resourceName, "policies"), - resource.TestCheckResourceAttrPair(dataSourceName, "resources", resourceName, "resources"), - resource.TestCheckResourceAttrPair(dataSourceName, "scopes", resourceName, "scopes"), + resource.TestCheckResourceAttr(dataSourceName, "resource_server_id", regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")), + resource.TestCheckResourceAttr(dataSourceName, "realm_id", realm), + resource.TestCheckResourceAttr(dataSourceName, "name", clientId), + resource.TestCheckResourceAttr(dataSourceName, "decision_strategy", "AFFIRMATIVE"), + resource.TestCheckResourceAttr(dataSourceName, "logic", "POSITIVE"), + resource.TestCheckResourceAttr(dataSourceName, "type", "js"), ), }, }, From eda5f46cc15eda5a80f1b275c1af73c9e0408856 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 16:40:15 +0300 Subject: [PATCH 38/47] test --- ...source_keycloak_openid_client_authorization_policy_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 54802ac2..307b2125 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -19,8 +19,8 @@ func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T Steps: []resource.TestStep{ { Config: testAccKeycloakOpenidClientAuthorizationPolicyConfig(realm, clientId), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(dataSourceName, "resource_server_id", regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")), + Check: resource.ComposeTestCheckFunc( + resource.TestMatchResourceAttr(dataSourceName, "resource_server_id", regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")), resource.TestCheckResourceAttr(dataSourceName, "realm_id", realm), resource.TestCheckResourceAttr(dataSourceName, "name", clientId), resource.TestCheckResourceAttr(dataSourceName, "decision_strategy", "AFFIRMATIVE"), From 26567d3d62066e99fce3caa0c329527c16f5713c Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 16:43:27 +0300 Subject: [PATCH 39/47] fixed service account tests --- ...esource_keycloak_openid_client_service_account_role_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index 76eae656..980e7393 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -149,8 +149,9 @@ func getKeycloakOpenidClientServiceAccountRoleFromState(s *terraform.State, reso serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] clientId := rs.Primary.Attributes["client_id"] role := rs.Primary.Attributes["role"] + id := rs.Primary.Id - serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, role) + serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id) if err != nil { return nil, fmt.Errorf("error getting service account role mapping: %s", err) } From 69a5c4fbbee84df710bb42796e84957c562eab2c Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 16:46:06 +0300 Subject: [PATCH 40/47] fixed typo --- ...resource_keycloak_openid_client_service_account_role_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index 980e7393..8a43659d 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -149,7 +149,7 @@ func getKeycloakOpenidClientServiceAccountRoleFromState(s *terraform.State, reso serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] clientId := rs.Primary.Attributes["client_id"] role := rs.Primary.Attributes["role"] - id := rs.Primary.Id + id := rs.Primary.ID serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id) if err != nil { From 0cdf594d1ad75c2c446fc079dc54b2e36adfbbfc Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 16:50:28 +0300 Subject: [PATCH 41/47] minor fix --- .../resource_keycloak_openid_client_service_account_role_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index 8a43659d..af283426 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -148,7 +148,6 @@ func getKeycloakOpenidClientServiceAccountRoleFromState(s *terraform.State, reso realmId := rs.Primary.Attributes["realm_id"] serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] clientId := rs.Primary.Attributes["client_id"] - role := rs.Primary.Attributes["role"] id := rs.Primary.ID serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id) From c9ef71bce1b16308407649d6af2538a53414a403 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 17:03:23 +0300 Subject: [PATCH 42/47] minor update --- ...data_source_keycloak_openid_client_test.go | 23 ++++++++++++------- ...openid_client_service_account_role_test.go | 4 ++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/provider/data_source_keycloak_openid_client_test.go b/provider/data_source_keycloak_openid_client_test.go index fdb5904f..ab6426c6 100644 --- a/provider/data_source_keycloak_openid_client_test.go +++ b/provider/data_source_keycloak_openid_client_test.go @@ -52,16 +52,23 @@ resource keycloak_realm test { } resource keycloak_openid_client test { - name = "%s" - client_id = "%s" - realm_id = "${keycloak_realm.test.id}" - description = "a test openid client" - standard_flow_enabled = true - access_type = "CONFIDENTIAL" - valid_redirect_uris = [ + name = "%s" + client_id = "%s" + realm_id = "${keycloak_realm.test.id}" + description = "a test openid client" + standard_flow_enabled = true + access_type = "CONFIDENTIAL" + service_accounts_enabled = true + client_secret = "secret" + valid_redirect_uris = [ "http://localhost:5555/callback", ] - client_secret = "secret" + authorization { + policy_enforcement_mode = "ENFORCING" + } + web_origins = [ + "http://localhost" + ] } data keycloak_openid_client test { diff --git a/provider/resource_keycloak_openid_client_service_account_role_test.go b/provider/resource_keycloak_openid_client_service_account_role_test.go index af283426..092e9166 100644 --- a/provider/resource_keycloak_openid_client_service_account_role_test.go +++ b/provider/resource_keycloak_openid_client_service_account_role_test.go @@ -123,11 +123,11 @@ func testAccCheckKeycloakOpenidClientServiceAccountRoleDestroy() resource.TestCh realmId := rs.Primary.Attributes["realm_id"] serviceAccountUserId := rs.Primary.Attributes["service_account_user_id"] clientId := rs.Primary.Attributes["client_id"] - role := rs.Primary.Attributes["role"] + id := rs.Primary.ID keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient) - serviceAccountRole, _ := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, role) + serviceAccountRole, _ := keycloakClient.GetOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id) if serviceAccountRole != nil { return fmt.Errorf("service account role exists") } From 517452be4c1bcc7b99a5b13932bf46371902ccf9 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 17:16:49 +0300 Subject: [PATCH 43/47] minor fix --- keycloak/openid_client_service_account_role.go | 3 ++- ..._source_keycloak_openid_client_authorization_policy_test.go | 2 +- provider/data_source_keycloak_openid_client_test.go | 3 --- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/keycloak/openid_client_service_account_role.go b/keycloak/openid_client_service_account_role.go index ffd5b4a0..f6d00b8a 100644 --- a/keycloak/openid_client_service_account_role.go +++ b/keycloak/openid_client_service_account_role.go @@ -31,7 +31,8 @@ func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceA func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) error { serviceAccountRoles := []OpenidClientServiceAccountRole{ { - Id: roleId, + Id: roleId, + ContainerId: clientId, }, } err := keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles) diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 307b2125..99b6742e 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -22,7 +22,7 @@ func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T Check: resource.ComposeTestCheckFunc( resource.TestMatchResourceAttr(dataSourceName, "resource_server_id", regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")), resource.TestCheckResourceAttr(dataSourceName, "realm_id", realm), - resource.TestCheckResourceAttr(dataSourceName, "name", clientId), + resource.TestCheckResourceAttr(dataSourceName, "name", "default"), resource.TestCheckResourceAttr(dataSourceName, "decision_strategy", "AFFIRMATIVE"), resource.TestCheckResourceAttr(dataSourceName, "logic", "POSITIVE"), resource.TestCheckResourceAttr(dataSourceName, "type", "js"), diff --git a/provider/data_source_keycloak_openid_client_test.go b/provider/data_source_keycloak_openid_client_test.go index ab6426c6..b8408e18 100644 --- a/provider/data_source_keycloak_openid_client_test.go +++ b/provider/data_source_keycloak_openid_client_test.go @@ -26,12 +26,9 @@ func TestAccKeycloakDataSourceOpenidClient_basic(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceName, "enabled", resourceName, "enabled"), resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"), resource.TestCheckResourceAttrPair(dataSourceName, "access_type", resourceName, "access_type"), - resource.TestCheckResourceAttrPair(dataSourceName, "client_secret", resourceName, "client_secret"), resource.TestCheckResourceAttrPair(dataSourceName, "standard_flow_enabled", resourceName, "standard_flow_enabled"), resource.TestCheckResourceAttrPair(dataSourceName, "implicit_flow_enabled", resourceName, "implicit_flow_enabled"), resource.TestCheckResourceAttrPair(dataSourceName, "direct_access_grants_enabled", resourceName, "direct_access_grants_enabled"), - resource.TestCheckResourceAttrPair(dataSourceName, "valid_redirect_uris", resourceName, "valid_redirect_uris"), - resource.TestCheckResourceAttrPair(dataSourceName, "web_origins", resourceName, "web_origins"), resource.TestCheckResourceAttrPair(dataSourceName, "service_account_user_id", resourceName, "service_account_user_id"), resource.TestCheckResourceAttrPair(dataSourceName, "service_accounts_enabled", resourceName, "service_accounts_enabled"), resource.TestCheckResourceAttrPair(dataSourceName, "resource_server_id", resourceName, "resource_server_id"), From fae15f045ba1f87303a0b63fc37ee1186db18d66 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 18:13:54 +0300 Subject: [PATCH 44/47] fixed delete request for service account role --- keycloak/openid_client_service_account_role.go | 14 +++++++------- ...loak_openid_client_authorization_policy_test.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/keycloak/openid_client_service_account_role.go b/keycloak/openid_client_service_account_role.go index f6d00b8a..45a385b1 100644 --- a/keycloak/openid_client_service_account_role.go +++ b/keycloak/openid_client_service_account_role.go @@ -8,10 +8,11 @@ type OpenidClientServiceAccountRole struct { Id string `json:"id"` RealmId string `json:"-"` ServiceAccountUserId string `json:"-"` - Name string `json:"name"` + Name string `json:"name,omitempty"` ClientRole bool `json:"clientRole"` Composite bool `json:"composite"` ContainerId string `json:"containerId"` + Description string `json:"description"` } func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceAccountRole *OpenidClientServiceAccountRole) error { @@ -29,13 +30,12 @@ func (keycloakClient *KeycloakClient) NewOpenidClientServiceAccountRole(serviceA } func (keycloakClient *KeycloakClient) DeleteOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId string) error { - serviceAccountRoles := []OpenidClientServiceAccountRole{ - { - Id: roleId, - ContainerId: clientId, - }, + serviceAccountRole, err := keycloakClient.GetOpenidClientServiceAccountRole(realm, serviceAccountUserId, clientId, roleId) + if err != nil { + return err } - err := keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles) + serviceAccountRoles := []OpenidClientServiceAccountRole{*serviceAccountRole} + err = keycloakClient.delete(fmt.Sprintf("/realms/%s/users/%s/role-mappings/clients/%s", realm, serviceAccountUserId, clientId), &serviceAccountRoles) if err != nil { return err } diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 99b6742e..35f8e6b7 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -23,7 +23,7 @@ func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T resource.TestMatchResourceAttr(dataSourceName, "resource_server_id", regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")), resource.TestCheckResourceAttr(dataSourceName, "realm_id", realm), resource.TestCheckResourceAttr(dataSourceName, "name", "default"), - resource.TestCheckResourceAttr(dataSourceName, "decision_strategy", "AFFIRMATIVE"), + resource.TestCheckResourceAttr(dataSourceName, "decision_strategy", "UNANIMOUS"), resource.TestCheckResourceAttr(dataSourceName, "logic", "POSITIVE"), resource.TestCheckResourceAttr(dataSourceName, "type", "js"), ), From d7c0e21d6b9fc93ee7f0232f50ba32ebc36c6041 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Fri, 10 May 2019 18:26:51 +0300 Subject: [PATCH 45/47] minor fix --- keycloak/openid_client_service_account_role.go | 2 +- ...a_source_keycloak_openid_client_authorization_policy_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/keycloak/openid_client_service_account_role.go b/keycloak/openid_client_service_account_role.go index 45a385b1..d8e6aa89 100644 --- a/keycloak/openid_client_service_account_role.go +++ b/keycloak/openid_client_service_account_role.go @@ -60,5 +60,5 @@ func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountRole(realm, s return &serviceAccountRole, nil } } - return nil, fmt.Errorf("No role with id %s found", roleId) + return &OpenidClientServiceAccountRole{}, nil } diff --git a/provider/data_source_keycloak_openid_client_authorization_policy_test.go b/provider/data_source_keycloak_openid_client_authorization_policy_test.go index 35f8e6b7..8016a98e 100644 --- a/provider/data_source_keycloak_openid_client_authorization_policy_test.go +++ b/provider/data_source_keycloak_openid_client_authorization_policy_test.go @@ -25,7 +25,7 @@ func TestAccKeycloakDataSourceOpenidClientAuthorizationPolicy_basic(t *testing.T resource.TestCheckResourceAttr(dataSourceName, "name", "default"), resource.TestCheckResourceAttr(dataSourceName, "decision_strategy", "UNANIMOUS"), resource.TestCheckResourceAttr(dataSourceName, "logic", "POSITIVE"), - resource.TestCheckResourceAttr(dataSourceName, "type", "js"), + resource.TestCheckResourceAttr(dataSourceName, "type", "resource"), ), }, }, From 8919a4ed48a228260728fef933932e31edd4bd48 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Sat, 11 May 2019 00:30:17 +0300 Subject: [PATCH 46/47] trigger build From a688cc0223106539a598288f74bf071307d40b39 Mon Sep 17 00:00:00 2001 From: Andrii Chubatiuk Date: Sat, 11 May 2019 12:59:20 +0300 Subject: [PATCH 47/47] added default resource removal --- keycloak/openid_client.go | 14 ++++++++++++++ keycloak/openid_client_authorization_resource.go | 14 ++++++++++++++ provider/resource_keycloak_openid_client.go | 6 ++++++ 3 files changed, 34 insertions(+) diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go index 6b47902c..9bf9ca22 100644 --- a/keycloak/openid_client.go +++ b/keycloak/openid_client.go @@ -21,6 +21,7 @@ type OpenidClientSecret struct { type OpenidClientAuthorizationSettings struct { PolicyEnforcementMode string `json:"policyEnforcementMode,omitempty"` AllowRemoteResourceManagement bool `json:"allowRemoteResourceManagement,omitempty"` + KeepDefaults bool `json:"-"` } type OpenidClient struct { @@ -105,6 +106,19 @@ func (keycloakClient *KeycloakClient) NewOpenidClient(client *OpenidClient) erro client.Id = getIdFromLocationHeader(location) + if authorizationSettings := client.AuthorizationSettings; authorizationSettings != nil { + if !(*authorizationSettings).KeepDefaults { + resource, err := keycloakClient.GetOpenidClientAuthorizationResourceByName(client.RealmId, client.Id, "default") + if err != nil { + return err + } + err = keycloakClient.DeleteOpenidClientAuthorizationResource(resource.RealmId, resource.ResourceServerId, resource.Id) + if err != nil { + return err + } + } + } + return nil } diff --git a/keycloak/openid_client_authorization_resource.go b/keycloak/openid_client_authorization_resource.go index cd8a722e..d1b0de6b 100644 --- a/keycloak/openid_client_authorization_resource.go +++ b/keycloak/openid_client_authorization_resource.go @@ -43,6 +43,20 @@ func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResource(realm return &resource, nil } +func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationResourceByName(realmId, resourceServerId, name string) (*OpenidClientAuthorizationResource, error) { + resources := []OpenidClientAuthorizationResource{} + params := map[string]string{"name": name} + err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource", realmId, resourceServerId), &resources, params) + if err != nil { + return nil, err + } + resource := resources[0] + resource.RealmId = realmId + resource.ResourceServerId = resourceServerId + resource.Name = name + return &resource, nil +} + func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationResource(resource *OpenidClientAuthorizationResource) error { err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/resource/%s", resource.RealmId, resource.ResourceServerId, resource.Id), resource) if err != nil { diff --git a/provider/resource_keycloak_openid_client.go b/provider/resource_keycloak_openid_client.go index ee54c8a1..4d07112c 100644 --- a/provider/resource_keycloak_openid_client.go +++ b/provider/resource_keycloak_openid_client.go @@ -114,6 +114,11 @@ func resourceKeycloakOpenidClient() *schema.Resource { Optional: true, Default: false, }, + "keep_defaults": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, }, }, @@ -179,6 +184,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient, openidClient.AuthorizationSettings = &keycloak.OpenidClientAuthorizationSettings{ PolicyEnforcementMode: authorizationSettings["policy_enforcement_mode"].(string), AllowRemoteResourceManagement: authorizationSettings["allow_remote_resource_management"].(bool), + KeepDefaults: authorizationSettings["keep_defaults"].(bool), } } else { openidClient.AuthorizationServicesEnabled = false