Skip to content

Commit

Permalink
add cache policy parameter to ldap user federation
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Groschupp committed Sep 4, 2020
1 parent 53d5d68 commit 1f1c4bd
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 9 deletions.
8 changes: 7 additions & 1 deletion docs/resources/ldap_user_federation.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ resource "keycloak_ldap_user_federation" "ldap_user_federation" {
- `batch_size_for_sync` - (Optional) The number of users to sync within a single transaction. Defaults to `1000`.
- `full_sync_period` - (Optional) How frequently Keycloak should sync all LDAP users, in seconds. Omit this property to disable periodic full sync.
- `changed_sync_period` - (Optional) How frequently Keycloak should sync changed LDAP users, in seconds. Omit this property to disable periodic changed users sync.
- `cache_policy` - (Optional) Can be one of `DEFAULT`, `EVICT_DAILY`, `EVICT_WEEKLY`, `MAX_LIFESPAN`, or `NO_CACHE`. Defaults to `DEFAULT`.
- `cache_policy` - (Optional) **Deprecated** Can be one of `DEFAULT`, `EVICT_DAILY`, `EVICT_WEEKLY`, `MAX_LIFESPAN`, or `NO_CACHE`. Defaults to `DEFAULT`.
- `cache` - (Optional) A block containing the cache settings.
- `policy` - (Optional) Can be one of `DEFAULT`, `EVICT_DAILY`, `EVICT_WEEKLY`, `MAX_LIFESPAN`, or `NO_CACHE`. Defaults to `DEFAULT`.
- `max_lifespan` - (Optional) Max lifespan of cache entry (duration string).
- `eviction_day` - (Optional) Day of the week the entry will become invalid on
- `eviction_hour` - (Optional) Hour of day the entry will become invalid on.
- `eviction_day` - (Optional) Minute of day the entry will become invalid on.
- `kerberos` - (Optional) A block containing the kerberos settings.
- `kerberos_realm` - (Required) The name of the kerberos realm, e.g. FOO.LOCAL.
- `server_principal` - (Required) The kerberos server principal, e.g. 'HTTP/host.foo.com@FOO.LOCAL'.
Expand Down
74 changes: 73 additions & 1 deletion keycloak/ldap_user_federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ type LdapUserFederation struct {
FullSyncPeriod int // either a number, in milliseconds, or -1 if full sync is disabled
ChangedSyncPeriod int // either a number, in milliseconds, or -1 if changed sync is disabled

CachePolicy string
CachePolicy string
MaxLifespan string // duration string (ex: 1h30m)
EvictionDay *int
EvictionHour *int
EvictionMinute *int
}

func convertFromLdapUserFederationToComponent(ldap *LdapUserFederation) (*component, error) {
Expand Down Expand Up @@ -173,6 +177,31 @@ func convertFromLdapUserFederationToComponent(ldap *LdapUserFederation) (*compon
componentConfig["readTimeout"] = []string{} // the keycloak API will not unset this unless the config is present with an empty array
}

componentConfig["evictionHour"] = []string{}
componentConfig["evictionMinute"] = []string{}
componentConfig["evictionDay"] = []string{}
componentConfig["maxLifespan"] = []string{}

if ldap.CachePolicy != "" {
if ldap.EvictionHour != nil {
componentConfig["evictionHour"] = []string{strconv.Itoa(*ldap.EvictionHour)}
}
if ldap.EvictionMinute != nil {
componentConfig["evictionMinute"] = []string{strconv.Itoa(*ldap.EvictionMinute)}
}
if ldap.EvictionDay != nil {
componentConfig["evictionDay"] = []string{strconv.Itoa(*ldap.EvictionDay)}
}

if ldap.MaxLifespan != "" {
maxLifespanMs, err := getMillisecondsFromDurationString(ldap.MaxLifespan)
if err != nil {
return nil, err
}
componentConfig["maxLifespan"] = []string{maxLifespanMs}
}
}

return &component{
Id: ldap.Id,
Name: ldap.Name,
Expand Down Expand Up @@ -324,6 +353,49 @@ func convertFromComponentToLdapUserFederation(component *component) (*LdapUserFe
ldap.ReadTimeout = readTimeoutDurationString
}

if maxLifespan, ok := component.getConfigOk("maxLifespan"); ok {
maxLifespanString, err := GetDurationStringFromMilliseconds(maxLifespan)
if err != nil {
return nil, err
}

ldap.MaxLifespan = maxLifespanString
}

defaultEvictioValue := -1

if evictionDay, ok := component.getConfigOk("evictionDay"); ok {
evictionDayInt, err := strconv.Atoi(evictionDay)
if err != nil {
return nil, fmt.Errorf("unable to parse `evictionDay`: %w", err)
}

ldap.EvictionDay = &evictionDayInt
} else {
ldap.EvictionDay = &defaultEvictioValue
}

if evictionHour, ok := component.getConfigOk("evictionHour"); ok {
evictionHourInt, err := strconv.Atoi(evictionHour)
if err != nil {
return nil, fmt.Errorf("unable to parse `evictionHour`: %w", err)
}

ldap.EvictionHour = &evictionHourInt
} else {
ldap.EvictionHour = &defaultEvictioValue
}
if evictionMinute, ok := component.getConfigOk("evictionMinute"); ok {
evictionMinuteInt, err := strconv.Atoi(evictionMinute)
if err != nil {
return nil, fmt.Errorf("unable to parse `evictionMinute`: %w", err)
}

ldap.EvictionMinute = &evictionMinuteInt
} else {
ldap.EvictionMinute = &defaultEvictioValue
}

return ldap, nil
}

Expand Down
94 changes: 89 additions & 5 deletions provider/resource_keycloak_ldap_user_federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,56 @@ func resourceKeycloakLdapUserFederation() *schema.Resource {
},

"cache_policy": {
Type: schema.TypeString,
Optional: true,
Default: "DEFAULT",
ValidateFunc: validation.StringInSlice(keycloakUserFederationCachePolicies, false),
Type: schema.TypeString,
Optional: true,
Default: "DEFAULT",
Deprecated: "use cache.policy instead",
ConflictsWith: []string{"cache"},
ValidateFunc: validation.StringInSlice(keycloakUserFederationCachePolicies, false),
},
"cache": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Description: "Settings regarding cache policy for this realm.",
ConflictsWith: []string{"cache_policy"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"policy": {
Type: schema.TypeString,
Optional: true,
Default: "DEFAULT",
ValidateFunc: validation.StringInSlice(keycloakUserFederationCachePolicies, false),
},
"max_lifespan": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: suppressDurationStringDiff,
Description: "Max lifespan of cache entry (duration string).",
},
"eviction_day": {
Type: schema.TypeInt,
Optional: true,
Default: "-1",
ValidateFunc: validation.All(validation.IntAtLeast(0), validation.IntAtMost(6)),
Description: "Day of the week the entry will become invalid on.",
},
"eviction_hour": {
Type: schema.TypeInt,
Optional: true,
Default: "-1",
ValidateFunc: validation.All(validation.IntAtLeast(0), validation.IntAtMost(23)),
Description: "Hour of day the entry will become invalid on.",
},
"eviction_minute": {
Type: schema.TypeInt,
Optional: true,
Default: "-1",
ValidateFunc: validation.All(validation.IntAtLeast(0), validation.IntAtMost(59)),
Description: "Minute of day the entry will become invalid on.",
},
},
},
},
},
}
Expand Down Expand Up @@ -289,6 +335,22 @@ func getLdapUserFederationFromData(data *schema.ResourceData) *keycloak.LdapUser
CachePolicy: data.Get("cache_policy").(string),
}

if cache, ok := data.GetOk("cache"); ok {
cache := cache.([]interface{})
cacheData := cache[0].(map[string]interface{})

evictionDay := cacheData["eviction_day"].(int)
evictionHour := cacheData["eviction_hour"].(int)
evictionMinute := cacheData["eviction_minute"].(int)

ldapUserFederation.MaxLifespan = cacheData["max_lifespan"].(string)

ldapUserFederation.EvictionDay = &evictionDay
ldapUserFederation.EvictionHour = &evictionHour
ldapUserFederation.EvictionMinute = &evictionMinute
ldapUserFederation.CachePolicy = cacheData["policy"].(string)
}

if kerberos, ok := data.GetOk("kerberos"); ok {
ldapUserFederation.AllowKerberosAuthentication = true
kerberosSettingsData := kerberos.(*schema.Set).List()[0]
Expand Down Expand Up @@ -353,7 +415,29 @@ func setLdapUserFederationData(data *schema.ResourceData, ldap *keycloak.LdapUse
data.Set("full_sync_period", ldap.FullSyncPeriod)
data.Set("changed_sync_period", ldap.ChangedSyncPeriod)

data.Set("cache_policy", ldap.CachePolicy)
if _, ok := data.GetOk("cache"); ok {
cachePolicySettings := make(map[string]interface{})

if ldap.MaxLifespan != "" {
cachePolicySettings["max_lifespan"] = ldap.MaxLifespan
}

if ldap.EvictionDay != nil {
cachePolicySettings["eviction_day"] = *ldap.EvictionDay
}
if ldap.EvictionHour != nil {
cachePolicySettings["eviction_hour"] = *ldap.EvictionHour
}
if ldap.EvictionMinute != nil {
cachePolicySettings["eviction_minute"] = *ldap.EvictionMinute
}

cachePolicySettings["policy"] = ldap.CachePolicy

data.Set("cache", []interface{}{cachePolicySettings})
} else {
data.Set("cache_policy", ldap.CachePolicy)
}
}

func resourceKeycloakLdapUserFederationCreate(data *schema.ResourceData, meta interface{}) error {
Expand Down
34 changes: 32 additions & 2 deletions provider/resource_keycloak_ldap_user_federation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ func generateRandomLdapKerberos(enabled bool) *keycloak.LdapUserFederation {
connectionTimeout, _ := keycloak.GetDurationStringFromMilliseconds(strconv.Itoa(acctest.RandIntRange(1, 3600) * 1000))
readTimeout, _ := keycloak.GetDurationStringFromMilliseconds(strconv.Itoa(acctest.RandIntRange(1, 3600) * 1000))

evictionDay := acctest.RandIntRange(0, 6)
evictionHour := acctest.RandIntRange(0, 23)
evictionMinute := acctest.RandIntRange(0, 59)

return &keycloak.LdapUserFederation{
RealmId: acctest.RandString(10),
Name: "terraform-" + acctest.RandString(10),
Expand All @@ -153,6 +157,10 @@ func generateRandomLdapKerberos(enabled bool) *keycloak.LdapUserFederation {
AllowKerberosAuthentication: true,
KeyTab: acctest.RandString(10),
KerberosRealm: acctest.RandString(10),
MaxLifespan: randomStringInSlice([]string{"1h", "2h", "3h"}),
EvictionDay: &evictionDay,
EvictionHour: &evictionHour,
EvictionMinute: &evictionMinute,
}
}

Expand Down Expand Up @@ -225,6 +233,10 @@ func TestAccKeycloakLdapUserFederation_basicUpdateAll(t *testing.T) {
firstReadTimeout, _ := keycloak.GetDurationStringFromMilliseconds(strconv.Itoa(acctest.RandIntRange(1, 3600) * 1000))
secondReadTimeout, _ := keycloak.GetDurationStringFromMilliseconds(strconv.Itoa(acctest.RandIntRange(1, 3600) * 1000))

evictionDay := acctest.RandIntRange(0, 6)
evictionHour := acctest.RandIntRange(0, 23)
evictionMinute := acctest.RandIntRange(0, 59)

firstLdap := &keycloak.LdapUserFederation{
RealmId: realmName,
Name: "terraform-" + acctest.RandString(10),
Expand All @@ -251,8 +263,16 @@ func TestAccKeycloakLdapUserFederation_basicUpdateAll(t *testing.T) {
AllowKerberosAuthentication: randomBool(),
KeyTab: acctest.RandString(10),
KerberosRealm: acctest.RandString(10),
MaxLifespan: randomStringInSlice([]string{"1h", "2h", "3h"}),
EvictionDay: &evictionDay,
EvictionHour: &evictionHour,
EvictionMinute: &evictionMinute,
}

evictionDay = acctest.RandIntRange(0, 6)
evictionHour = acctest.RandIntRange(0, 23)
evictionMinute = acctest.RandIntRange(0, 59)

secondLdap := &keycloak.LdapUserFederation{
RealmId: realmName,
Name: "terraform-" + acctest.RandString(10),
Expand All @@ -279,6 +299,10 @@ func TestAccKeycloakLdapUserFederation_basicUpdateAll(t *testing.T) {
AllowKerberosAuthentication: randomBool(),
KeyTab: acctest.RandString(10),
KerberosRealm: acctest.RandString(10),
MaxLifespan: randomStringInSlice([]string{"1h", "2h", "3h"}),
EvictionDay: &evictionDay,
EvictionHour: &evictionHour,
EvictionMinute: &evictionMinute,
}

resource.Test(t, resource.TestCase{
Expand Down Expand Up @@ -659,9 +683,15 @@ resource "keycloak_ldap_user_federation" "openldap" {
kerberos_realm = "%s"
}
cache_policy = "%s"
cache {
policy = "%s"
max_lifespan = "%s"
eviction_day = %d
eviction_hour = %d
eviction_minute = %d
}
}
`, ldap.RealmId, ldap.Name, ldap.Enabled, ldap.UsernameLDAPAttribute, ldap.RdnLDAPAttribute, ldap.UuidLDAPAttribute, arrayOfStringsForTerraformResource(ldap.UserObjectClasses), ldap.ConnectionUrl, ldap.UsersDn, ldap.BindDn, ldap.BindCredential, ldap.SearchScope, ldap.ValidatePasswordPolicy, ldap.UseTruststoreSpi, ldap.ConnectionTimeout, ldap.ReadTimeout, ldap.Pagination, ldap.BatchSizeForSync, ldap.FullSyncPeriod, ldap.ChangedSyncPeriod, ldap.ServerPrincipal, ldap.UseKerberosForPasswordAuthentication, ldap.KeyTab, ldap.KerberosRealm, ldap.CachePolicy)
`, ldap.RealmId, ldap.Name, ldap.Enabled, ldap.UsernameLDAPAttribute, ldap.RdnLDAPAttribute, ldap.UuidLDAPAttribute, arrayOfStringsForTerraformResource(ldap.UserObjectClasses), ldap.ConnectionUrl, ldap.UsersDn, ldap.BindDn, ldap.BindCredential, ldap.SearchScope, ldap.ValidatePasswordPolicy, ldap.UseTruststoreSpi, ldap.ConnectionTimeout, ldap.ReadTimeout, ldap.Pagination, ldap.BatchSizeForSync, ldap.FullSyncPeriod, ldap.ChangedSyncPeriod, ldap.ServerPrincipal, ldap.UseKerberosForPasswordAuthentication, ldap.KeyTab, ldap.KerberosRealm, ldap.CachePolicy, ldap.MaxLifespan, *ldap.EvictionDay, *ldap.EvictionHour, *ldap.EvictionMinute)
}

func testKeycloakLdapUserFederation_basicWithAttrValidation(attr, realm, ldap, val string) string {
Expand Down

0 comments on commit 1f1c4bd

Please sign in to comment.