Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for user attribute value with length bigger than 255 symbols #132

Merged
merged 7 commits into from
Jul 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions keycloak/identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ type IdentityProviderConfig struct {
Key string `json:"key,omitempty"`
HostIp string `json:"hostIp,omitempty"`
UseJwksUrl KeycloakBoolQuoted `json:"useJwksUrl,omitempty"`
JwksUrl string `json:"jwksUrl,omitempty"`
ClientId string `json:"clientId,omitempty"`
ClientSecret string `json:"clientSecret,omitempty"`
DisableUserInfo KeycloakBoolQuoted `json:"disableUserInfo"`
UserInfoUrl string `json:"userInfoUrl,omitempty"`
HideOnLoginPage KeycloakBoolQuoted `json:"hideOnLoginPage"`
NameIDPolicyFormat string `json:"nameIDPolicyFormat,omitempty"`
SingleLogoutServiceUrl string `json:"singleLogoutServiceUrl,omitempty"`
Expand All @@ -32,6 +34,7 @@ type IdentityProviderConfig struct {
TokenUrl string `json:"tokenUrl,omitempty"`
LoginHint string `json:"loginHint,omitempty"`
UILocales KeycloakBoolQuoted `json:"uiLocales,omitempty"`
LogoutUrl string `json:"logoutUrl,omitempty"`
}

type IdentityProvider struct {
Expand Down
28 changes: 23 additions & 5 deletions provider/resource_keycloak_oidc_identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ func resourceKeycloakOidcIdentityProvider() *schema.Resource {
Sensitive: true,
Description: "Client Secret.",
},
"disable_user_info": {
Type: schema.TypeBool,
"user_info_url": {
Type: schema.TypeString,
Optional: true,
Default: false,
Description: "Disable User Info.",
Description: "User Info URL",
},
"jwks_url": {
Type: schema.TypeString,
Optional: true,
Description: "JSON Web Key Set URL",
},
"hide_on_login_page": {
Type: schema.TypeBool,
Expand All @@ -52,6 +56,11 @@ func resourceKeycloakOidcIdentityProvider() *schema.Resource {
Required: true,
Description: "Token URL.",
},
"logout_url": {
Type: schema.TypeString,
Optional: true,
Description: "Logout URL",
},
"login_hint": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -80,12 +89,18 @@ func getOidcIdentityProviderFromData(data *schema.ResourceData) (*keycloak.Ident
ValidateSignature: keycloak.KeycloakBoolQuoted(data.Get("validate_signature").(bool)),
AuthorizationUrl: data.Get("authorization_url").(string),
ClientId: data.Get("client_id").(string),
DisableUserInfo: keycloak.KeycloakBoolQuoted(data.Get("disable_user_info").(bool)),
HideOnLoginPage: keycloak.KeycloakBoolQuoted(data.Get("hide_on_login_page").(bool)),
TokenUrl: data.Get("token_url").(string),
LogoutUrl: data.Get("logout_url").(string),
UILocales: keycloak.KeycloakBoolQuoted(data.Get("ui_locales").(bool)),
LoginHint: data.Get("login_hint").(string),
JwksUrl: data.Get("jwks_url").(string),
UserInfoUrl: data.Get("user_info_url").(string),
}
_, useJwksUrl := data.GetOk("jwks_url")
rec.Config.UseJwksUrl = keycloak.KeycloakBoolQuoted(useJwksUrl)
_, enableUserInfo := data.GetOk("user_info_url")
rec.Config.DisableUserInfo = keycloak.KeycloakBoolQuoted(!enableUserInfo)

if data.HasChange("client_secret") {
rec.Config.ClientSecret = data.Get("client_secret").(string)
Expand All @@ -98,10 +113,13 @@ func setOidcIdentityProviderData(data *schema.ResourceData, identityProvider *ke
setIdentityProviderData(data, identityProvider)
data.Set("backchannel_supported", identityProvider.Config.BackchannelSupported)
data.Set("use_jwks_url", identityProvider.Config.UseJwksUrl)
data.Set("jwks_url", identityProvider.Config.JwksUrl)
data.Set("logout_url", identityProvider.Config.LogoutUrl)
data.Set("validate_signature", identityProvider.Config.ValidateSignature)
data.Set("authorization_url", identityProvider.Config.AuthorizationUrl)
data.Set("client_id", identityProvider.Config.ClientId)
data.Set("disable_user_info", identityProvider.Config.DisableUserInfo)
data.Set("user_info_url", identityProvider.Config.UserInfoUrl)
data.Set("hide_on_login_page", identityProvider.Config.HideOnLoginPage)
data.Set("token_url", identityProvider.Config.TokenUrl)
data.Set("login_hint", identityProvider.Config.LoginHint)
Expand Down
26 changes: 21 additions & 5 deletions provider/resource_keycloak_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strings"
)

const MAX_ATTRIBUTE_VALUE_LEN = 255

func resourceKeycloakUser() *schema.Resource {
return &schema.Resource{
Create: resourceKeycloakUserCreate,
Expand Down Expand Up @@ -110,7 +112,7 @@ 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), ",")
attributes[key] = splitLen(value.(string), MAX_ATTRIBUTE_VALUE_LEN)
}
}

Expand Down Expand Up @@ -138,24 +140,38 @@ func getUserFederatedIdentitiesFromData(data []interface{}) *keycloak.FederatedI
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),
IdentityProvider: federatedIdentitiesData["identity_provider"].(string),
UserId: federatedIdentitiesData["user_id"].(string),
UserName: federatedIdentitiesData["user_name"].(string),
}
federatedIdentities = append(federatedIdentities, federatedIdentity)
}
return &federatedIdentities
}

func mapFromUserToData(data *schema.ResourceData, user *keycloak.User) {
federatedIdentities := []interface{}{}
for _, federatedIdentity := range user.FederatedIdentities {
identity := map[string]interface{}{
"identity_provider": federatedIdentity.IdentityProvider,
"user_id": federatedIdentity.UserId,
"user_name": federatedIdentity.UserName,
}
federatedIdentities = append(federatedIdentities, identity)
}
attributes := map[string]string{}
for k, v := range user.Attributes {
attributes[k] = strings.Join(v, "")
}
data.SetId(user.Id)

data.Set("realm_id", user.RealmId)
data.Set("username", user.Username)
data.Set("email", user.Email)
data.Set("first_name", user.FirstName)
data.Set("last_name", user.LastName)
data.Set("enabled", user.Enabled)
data.Set("attributes", attributes)
data.Set("federated_identity", federatedIdentities)
}

func resourceKeycloakUserCreate(data *schema.ResourceData, meta interface{}) error {
Expand Down
41 changes: 29 additions & 12 deletions provider/resource_keycloak_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
func TestAccKeycloakUser_basic(t *testing.T) {
realmName := "terraform-" + acctest.RandString(10)
username := "terraform-user-" + acctest.RandString(10)
attributeName := "terraform-attribute-" + acctest.RandString(10)
attributeValue := acctest.RandString(300)

resourceName := "keycloak_user.user"

Expand All @@ -27,7 +29,7 @@ func TestAccKeycloakUser_basic(t *testing.T) {
CheckDestroy: testAccCheckKeycloakUserDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakUser_basic(realmName, username),
Config: testKeycloakUser_basic(realmName, username, attributeName, attributeValue),
Check: testAccCheckKeycloakUserExists(resourceName),
},
{
Expand Down Expand Up @@ -69,7 +71,8 @@ func TestAccKeycloakUser_createAfterManualDestroy(t *testing.T) {

realmName := "terraform-" + acctest.RandString(10)
username := "terraform-user-" + acctest.RandString(10)

attributeName := "terraform-attribute-" + acctest.RandString(10)
attributeValue := acctest.RandString(300)
resourceName := "keycloak_user.user"

resource.Test(t, resource.TestCase{
Expand All @@ -78,7 +81,7 @@ func TestAccKeycloakUser_createAfterManualDestroy(t *testing.T) {
CheckDestroy: testAccCheckKeycloakUserDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakUser_basic(realmName, username),
Config: testKeycloakUser_basic(realmName, username, attributeName, attributeValue),
Check: resource.ComposeTestCheckFunc(
testAccCheckKeycloakUserExists(resourceName),
testAccCheckKeycloakUserFetch(resourceName, user),
Expand All @@ -93,7 +96,7 @@ func TestAccKeycloakUser_createAfterManualDestroy(t *testing.T) {
t.Fatal(err)
}
},
Config: testKeycloakUser_basic(realmName, username),
Config: testKeycloakUser_basic(realmName, username, attributeName, attributeValue),
Check: testAccCheckKeycloakUserExists(resourceName),
},
},
Expand Down Expand Up @@ -134,6 +137,8 @@ func TestAccKeycloakUser_updateUsername(t *testing.T) {
realmName := "terraform-" + acctest.RandString(10)
usernameOne := "terraform-user-" + acctest.RandString(10)
usernameTwo := "terraform-user-" + acctest.RandString(10)
attributeName := "terraform-attribute-" + acctest.RandString(10)
attributeValue := acctest.RandString(300)

resourceName := "keycloak_user.user"

Expand All @@ -143,14 +148,14 @@ func TestAccKeycloakUser_updateUsername(t *testing.T) {
CheckDestroy: testAccCheckKeycloakUserDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakUser_basic(realmName, usernameOne),
Config: testKeycloakUser_basic(realmName, usernameOne, attributeName, attributeValue),
Check: resource.ComposeTestCheckFunc(
testAccCheckKeycloakUserExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "username", usernameOne),
),
},
{
Config: testKeycloakUser_basic(realmName, usernameTwo),
Config: testKeycloakUser_basic(realmName, usernameTwo, attributeName, attributeValue),
Check: resource.ComposeTestCheckFunc(
testAccCheckKeycloakUserExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "username", usernameTwo),
Expand Down Expand Up @@ -227,13 +232,20 @@ func TestAccKeycloakUser_updateInPlace(t *testing.T) {
}

func TestAccKeycloakUser_unsetOptionalAttributes(t *testing.T) {
attributeName := "terraform-attribute-" + acctest.RandString(10)
userWithOptionalAttributes := &keycloak.User{
RealmId: "terraform-" + acctest.RandString(10),
Username: "terraform-user-" + acctest.RandString(10),
Email: fmt.Sprintf("%s@gmail.com", acctest.RandString(10)),
FirstName: acctest.RandString(10),
LastName: acctest.RandString(10),
Enabled: randomBool(),
Attributes: map[string][]string{
attributeName: {
acctest.RandString(255),
acctest.RandString(12),
},
},
}

resourceName := "keycloak_user.user"
Expand All @@ -248,7 +260,7 @@ func TestAccKeycloakUser_unsetOptionalAttributes(t *testing.T) {
Check: testAccCheckKeycloakUserExists(resourceName),
},
{
Config: testKeycloakUser_basic(userWithOptionalAttributes.RealmId, userWithOptionalAttributes.Username),
Config: testKeycloakUser_basic(userWithOptionalAttributes.RealmId, userWithOptionalAttributes.Username, attributeName, strings.Join(userWithOptionalAttributes.Attributes[attributeName], "")),
Check: resource.ComposeTestCheckFunc(
testAccCheckKeycloakUserExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "email", ""),
Expand All @@ -263,14 +275,16 @@ func TestAccKeycloakUser_unsetOptionalAttributes(t *testing.T) {
func TestAccKeycloakUser_validateLowercaseUsernames(t *testing.T) {
realmName := "terraform-" + acctest.RandString(10)
username := "terraform-user-" + strings.ToUpper(acctest.RandString(10))
attributeName := "terraform-attribute-" + acctest.RandString(10)
attributeValue := acctest.RandString(300)

resource.Test(t, resource.TestCase{
Providers: testAccProviders,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakUserDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakUser_basic(realmName, username),
Config: testKeycloakUser_basic(realmName, username, attributeName, attributeValue),
ExpectError: regexp.MustCompile("expected username .+ to be all lowercase"),
},
},
Expand Down Expand Up @@ -376,7 +390,7 @@ func getUserFromState(s *terraform.State, resourceName string) (*keycloak.User,
return user, nil
}

func testKeycloakUser_basic(realm, username string) string {
func testKeycloakUser_basic(realm, username, attributeName, attributeValue string) string {
return fmt.Sprintf(`
resource "keycloak_realm" "realm" {
realm = "%s"
Expand All @@ -385,8 +399,11 @@ resource "keycloak_realm" "realm" {
resource "keycloak_user" "user" {
realm_id = "${keycloak_realm.realm.id}"
username = "%s"
attributes = {
"%s" = "%s"
}
}
`, realm, username)
`, realm, username, attributeName, attributeValue)
}

func testKeycloakUser_initialPassword(realm, username string, password string, clientId string) string {
Expand All @@ -398,10 +415,10 @@ resource "keycloak_realm" "realm" {
resource "keycloak_openid_client" "client" {
realm_id = "${keycloak_realm.realm.id}"
client_id = "%s"

name = "test client"
enabled = true

access_type = "PUBLIC"
direct_access_grants_enabled = true
}
Expand Down
18 changes: 18 additions & 0 deletions provider/utils.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
package provider

import (
"bytes"
"github.com/hashicorp/terraform/helper/schema"
"github.com/mrparkers/terraform-provider-keycloak/keycloak"
"log"
"time"
)

func splitLen(s string, n int) []string {
sub := ""
subs := []string{}
runes := bytes.Runes([]byte(s))
l := len(runes)
for i, r := range runes {
sub = sub + string(r)
if (i+1)%n == 0 {
subs = append(subs, sub)
sub = ""
} else if (i + 1) == l {
subs = append(subs, sub)
}
}
return subs
}

func keys(data map[string]string) []string {
var result = []string{}
for k := range data {
Expand Down