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

add cache policy parameter to ldap user federation #376

Merged
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
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