in providers/keycloak/generator.go [349:633]
func (g *RealmGenerator) PostConvertHook() error {
mapRealmIDs := map[string]string{}
mapUserFederationIDs := map[string]string{}
mapGroupIDs := map[string]string{}
mapClientIDs := map[string]string{}
mapClientNames := map[string]string{}
mapClientClientIDs := map[string]string{}
mapClientClientNames := map[string]string{}
mapServiceAccountUserIDs := map[string]string{}
mapRoleIDs := map[string]string{}
mapClientRoleNames := map[string]string{}
mapClientRoleShortNames := map[string]string{}
mapScopeNames := map[string]string{}
mapUserNames := map[string]string{}
mapGroupNames := map[string]string{}
mapAuthenticationFlowAliases := map[string]string{}
mapAuthenticationExecutionIDs := map[string]string{}
// Set slices to be able to map IDs with Terraform variables
for _, r := range g.Resources {
if r.InstanceInfo.Type != "keycloak_realm" &&
r.InstanceInfo.Type != "keycloak_ldap_user_federation" &&
r.InstanceInfo.Type != "keycloak_group" &&
r.InstanceInfo.Type != "keycloak_openid_client" &&
r.InstanceInfo.Type != "keycloak_role" &&
r.InstanceInfo.Type != "keycloak_openid_client_scope" &&
r.InstanceInfo.Type != "keycloak_user" &&
r.InstanceInfo.Type != "keycloak_authentication_flow" &&
r.InstanceInfo.Type != "keycloak_authentication_subflow" &&
r.InstanceInfo.Type != "keycloak_authentication_execution" {
continue
}
if r.InstanceInfo.Type == "keycloak_realm" {
mapRealmIDs[r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
}
if r.InstanceInfo.Type == "keycloak_ldap_user_federation" {
mapUserFederationIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
}
if r.InstanceInfo.Type == "keycloak_group" {
mapGroupIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
mapGroupNames[r.Item["realm_id"].(string)+"_"+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
}
if r.InstanceInfo.Type == "keycloak_openid_client" {
mapClientIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
mapClientNames[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = r.Item["client_id"].(string)
mapClientClientNames[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".client_id}"
mapClientClientIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.Attributes["client_id"]] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".client_id}"
if _, exist := r.InstanceState.Attributes["service_account_user_id"]; exist {
mapServiceAccountUserIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.Attributes["service_account_user_id"]] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".service_account_user_id}"
}
}
if r.InstanceInfo.Type == "keycloak_openid_client_scope" {
mapScopeNames[r.Item["realm_id"].(string)+"_"+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
}
if r.InstanceInfo.Type == "keycloak_user" {
mapUserNames[r.Item["realm_id"].(string)+"_"+r.Item["username"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".username}"
}
if r.InstanceInfo.Type == "keycloak_authentication_flow" || r.InstanceInfo.Type == "keycloak_authentication_subflow" {
mapAuthenticationFlowAliases[r.Item["realm_id"].(string)+"_"+r.Item["alias"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".alias}"
}
if r.InstanceInfo.Type == "keycloak_authentication_execution" {
mapAuthenticationExecutionIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
}
}
// Set slices to be able to map IDs with Terraform variables
// Separate loop for roles to avoid fetching with a key that is not present in the map
for _, r := range g.Resources {
if r.InstanceInfo.Type == "keycloak_role" {
mapRoleIDs[r.Item["realm_id"].(string)+"_"+r.InstanceState.ID] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".id}"
if _, exist := r.Item["client_id"]; exist {
mapClientRoleNames[r.Item["realm_id"].(string)+"_"+mapClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]+"."+r.Item["name"].(string)] = mapClientClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)] + ".${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
mapClientRoleShortNames[r.Item["realm_id"].(string)+"_"+mapClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]+"."+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
} else {
mapClientRoleNames[r.Item["realm_id"].(string)+"_"+r.Item["name"].(string)] = "${" + r.InstanceInfo.Type + "." + r.ResourceName + ".name}"
}
}
}
// For each resource, modify import if needed...
for i, r := range g.Resources {
// Escape keycloak text inputs not to get unpredictable results or errors when Terraform will try to interpret variables ($ vs $$)
// TODO: ensure that we escape all existing fields
if strings.Contains(r.InstanceState.Attributes["consent_screen_text"], "$") {
g.Resources[i].Item["consent_screen_text"] = strings.ReplaceAll(r.InstanceState.Attributes["consent_screen_text"], "$", "$$")
}
if strings.Contains(r.InstanceState.Attributes["name"], "$") {
g.Resources[i].Item["name"] = strings.ReplaceAll(r.InstanceState.Attributes["name"], "$", "$$")
}
if strings.Contains(r.InstanceState.Attributes["description"], "$") {
g.Resources[i].Item["description"] = strings.ReplaceAll(r.InstanceState.Attributes["description"], "$", "$$")
}
if strings.Contains(r.InstanceState.Attributes["root_url"], "$") {
g.Resources[i].Item["root_url"] = strings.ReplaceAll(r.InstanceState.Attributes["root_url"], "$", "$$")
}
// Sort supported_locales to get reproducible results for keycloak_realm resources
if r.InstanceInfo.Type == "keycloak_realm" {
if _, exist := r.Item["internationalization"]; exist {
for _, v := range r.Item["internationalization"].([]interface{}) {
sortedSupportedLocales := make([]string, len(v.(map[string]interface{})["supported_locales"].([]interface{})))
for k, vv := range v.(map[string]interface{})["supported_locales"].([]interface{}) {
sortedSupportedLocales[k] = vv.(string)
}
sort.Strings(sortedSupportedLocales)
v.(map[string]interface{})["supported_locales"] = sortedSupportedLocales
}
}
}
// Sort group_ids to get reproducible results for keycloak_default_groups resources
// Set an empty string slice if the attribute doesn't exist as it is mandatory
if r.InstanceInfo.Type == "keycloak_default_groups" {
if _, exist := r.Item["group_ids"]; exist {
renamedGroupIDs := make([]string, len(r.Item["group_ids"].([]interface{})))
for k, v := range r.Item["group_ids"].([]interface{}) {
renamedGroupIDs[k] = mapGroupIDs[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedGroupIDs)
g.Resources[i].Item["group_ids"] = renamedGroupIDs
} else {
g.Resources[i].Item["group_ids"] = []string{}
}
}
// Sort valid_redirect_uris and web_origins to get reproducible results for keycloak_openid_client resources
if r.InstanceInfo.Type == "keycloak_openid_client" {
if _, exist := r.Item["valid_redirect_uris"]; exist {
sortedValidRedirectUris := make([]string, len(r.Item["valid_redirect_uris"].([]interface{})))
for k, v := range r.Item["valid_redirect_uris"].([]interface{}) {
sortedValidRedirectUris[k] = v.(string)
}
sort.Strings(sortedValidRedirectUris)
g.Resources[i].Item["valid_redirect_uris"] = sortedValidRedirectUris
}
if _, exist := r.Item["web_origins"]; exist {
sortedWebOrigins := make([]string, len(r.Item["web_origins"].([]interface{})))
for k, v := range r.Item["web_origins"].([]interface{}) {
sortedWebOrigins[k] = v.(string)
}
sort.Strings(sortedWebOrigins)
g.Resources[i].Item["web_origins"] = sortedWebOrigins
}
}
// Sort composite_roles to get reproducible results for keycloak_role resources
if _, exist := r.Item["composite_roles"]; exist && r.InstanceInfo.Type == "keycloak_role" {
renamedCompositeRoles := make([]string, len(r.Item["composite_roles"].([]interface{})))
for k, v := range r.Item["composite_roles"].([]interface{}) {
renamedCompositeRoles[k] = mapRoleIDs[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedCompositeRoles)
g.Resources[i].Item["composite_roles"] = renamedCompositeRoles
}
// Sort default_scopes to get reproducible results for keycloak_openid_client_default_scopes resources
if _, exist := r.Item["default_scopes"]; exist && r.InstanceInfo.Type == "keycloak_openid_client_default_scopes" {
renamedScopes := make([]string, len(r.Item["default_scopes"].([]interface{})))
for k, v := range r.Item["default_scopes"].([]interface{}) {
renamedScopes[k] = mapScopeNames[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedScopes)
g.Resources[i].Item["default_scopes"] = renamedScopes
}
// Sort optional_scopes to get reproducible results for keycloak_openid_client_optional_scopes resources
if _, exist := r.Item["optional_scopes"]; exist && r.InstanceInfo.Type == "keycloak_openid_client_optional_scopes" {
renamedScopes := make([]string, len(r.Item["optional_scopes"].([]interface{})))
for k, v := range r.Item["optional_scopes"].([]interface{}) {
renamedScopes[k] = mapScopeNames[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(renamedScopes)
g.Resources[i].Item["optional_scopes"] = renamedScopes
}
// Sort role_ids to get reproducible results for keycloak_group_roles resources
if r.InstanceInfo.Type == "keycloak_group_roles" {
if roleIDs, ok := r.Item["role_ids"].([]interface{}); ok {
sortedRoles := make([]string, len(roleIDs))
for k, v := range roleIDs {
sortedRoles[k] = mapRoleIDs[r.Item["realm_id"].(string)+"_"+v.(string)]
}
sort.Strings(sortedRoles)
g.Resources[i].Item["role_ids"] = sortedRoles
} else {
g.Resources[i].Item["role_ids"] = []string{}
}
}
// Sort members to get reproducible results for keycloak_group_memberships resources
// Map members to keycloak_user.foo.username Terraform variables
if r.InstanceInfo.Type == "keycloak_group_memberships" {
sortedMembers := make([]string, len(r.Item["members"].([]interface{})))
for k, v := range r.Item["members"].([]interface{}) {
if mapUserNames[r.Item["realm_id"].(string)+"_"+v.(string)] != "" {
sortedMembers[k] = mapUserNames[r.Item["realm_id"].(string)+"_"+v.(string)]
} else {
sortedMembers[k] = v.(string)
}
}
sort.Strings(sortedMembers)
g.Resources[i].Item["members"] = sortedMembers
}
// Map ldap_user_federation_id attributes to keycloak_ldap_user_federation.foo.id Terraform variables for ldap mappers resources
if r.InstanceInfo.Type == "keycloak_ldap_full_name_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_group_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_role_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_hardcoded_group_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_hardcoded_role_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_msad_lds_user_account_control_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_msad_user_account_control_mapper" ||
r.InstanceInfo.Type == "keycloak_ldap_user_attribute_mapper" {
g.Resources[i].Item["ldap_user_federation_id"] = mapUserFederationIDs[r.Item["realm_id"].(string)+"_"+g.Resources[i].Item["ldap_user_federation_id"].(string)]
}
// Map group to keycloak_group.foo.name Terraform variables for ldap hardcoded group mapper resources
if r.InstanceInfo.Type == "keycloak_ldap_hardcoded_group_mapper" {
g.Resources[i].Item["group"] = mapGroupNames[r.Item["realm_id"].(string)+"_"+r.Item["group"].(string)]
}
// Map role to Terraform variables for ldap hardcoded role mapper resources
if r.InstanceInfo.Type == "keycloak_ldap_hardcoded_role_mapper" {
g.Resources[i].Item["role"] = mapClientRoleNames[r.Item["realm_id"].(string)+"_"+r.Item["role"].(string)]
}
// Map parent_id to keycloak_group.foo.id Terraform variables for keycloak_group resources
if _, exist := r.Item["parent_id"]; exist && r.InstanceInfo.Type == "keycloak_group" {
g.Resources[i].Item["parent_id"] = mapGroupIDs[r.Item["realm_id"].(string)+"_"+r.Item["parent_id"].(string)]
}
// Map group_id to keycloak_group.foo.id Terraform variables for keycloak_group_memberships and keycloak_group_roles resources
if r.InstanceInfo.Type == "keycloak_group_memberships" || r.InstanceInfo.Type == "keycloak_group_roles" {
g.Resources[i].Item["group_id"] = mapGroupIDs[r.Item["realm_id"].(string)+"_"+r.Item["group_id"].(string)]
}
// Map service_account_user_id to keycloak_openid_client.foo.service_account_user_id Terraform variables for service account role resources
if r.InstanceInfo.Type == "keycloak_openid_client_service_account_role" {
g.Resources[i].Item["service_account_user_id"] = mapServiceAccountUserIDs[r.Item["realm_id"].(string)+"_"+r.Item["service_account_user_id"].(string)]
g.Resources[i].Item["role"] = mapClientRoleShortNames[r.Item["realm_id"].(string)+"_"+mapClientNames[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]+"."+r.Item["role"].(string)]
}
// Map client_id attributes to keycloak_openid_client.foo.id Terraform variables for open id mappers resources
if _, exist := r.Item["client_id"]; exist && (r.InstanceInfo.Type == "keycloak_openid_client_service_account_role" ||
r.InstanceInfo.Type == "keycloak_openid_audience_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_audience_resolve_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_full_name_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_group_membership_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_hardcoded_claim_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_hardcoded_role_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_script_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_attribute_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_client_role_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_property_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_realm_role_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_user_session_note_protocol_mapper" ||
r.InstanceInfo.Type == "keycloak_openid_client_default_scopes" ||
r.InstanceInfo.Type == "keycloak_openid_client_optional_scopes" ||
r.InstanceInfo.Type == "keycloak_role") {
g.Resources[i].Item["client_id"] = mapClientIDs[r.Item["realm_id"].(string)+"_"+r.Item["client_id"].(string)]
}
// Map included_client_audience to keycloak_openid_client.foo.client_id Terraform variables for open id audience mapper resources
if _, exist := r.Item["included_client_audience"]; exist && r.InstanceInfo.Type == "keycloak_openid_audience_protocol_mapper" {
g.Resources[i].Item["included_client_audience"] = mapClientClientIDs[r.Item["realm_id"].(string)+"_"+r.Item["included_client_audience"].(string)]
}
// Map parent_flow_alias attributes to keycloak_authentication_(sub)flow.foo.alias Terraform variables for authentication subflow and execution resources
if r.InstanceInfo.Type == "keycloak_authentication_subflow" || r.InstanceInfo.Type == "keycloak_authentication_execution" {
g.Resources[i].Item["parent_flow_alias"] = mapAuthenticationFlowAliases[r.Item["realm_id"].(string)+"_"+r.Item["parent_flow_alias"].(string)]
}
// Map execution_id attributes to keycloak_authentication_execution_config.foo.execution_id Terraform variables for authentication execution config resources
if r.InstanceInfo.Type == "keycloak_authentication_execution_config" {
g.Resources[i].Item["execution_id"] = mapAuthenticationExecutionIDs[r.Item["realm_id"].(string)+"_"+r.Item["execution_id"].(string)]
}
// Map realm_id attributes to keycloak_realm.foo.id Terraform variables for all the resources (almost all resources have this attribute)
if _, exist := r.Item["realm_id"]; exist {
g.Resources[i].Item["realm_id"] = mapRealmIDs[r.Item["realm_id"].(string)]
}
}
return nil
}