Keycloak Importer
keycloak Importer takes a json file with the same format as a keycloak realm export and use it to import ressources in a given realm :
- client scope & their mapper
- client
- groups
- roles (client roles & realm roles)
- users
The module will create or update depending on if the ressource exists or not, deletion is not currently supported.
Installation
The configuration can be tweaked with the following keys :
podAnnotations: Additional annotations to set on the pods.podLabels: Additional labels to set on the pods.config:keycloak: this is a yaml file which configure the general behaviour of the keycloak importer. An exemple below provide more information about each configuration key.import: this is a json file which contains all the resources, users and realm configuration (only at creation) you wish to import.
general configuration
## Default value are that of a default keycloak installation
# keycloak client-id that has access to the /realms/* endpoint
clientId: admin-cli
# Credentials of the user you wish to use for the import
username: <user>
password: <password>
# kind of grant to use to authenticate with keycloak. Only password is currently supported.
grantType: password
# Keycloak URL
baseUrl: https://auth.kosmos.wip
# Whether to skip certificate verification when querying keycloak in https
skipCertCheck: true
# whether to create the realm if it is missing
createRealm: false
Import file
The format of the import file is based on Realm Import and accept the following keys (any difference from the official representation will be noted) :
- realm : this is the key used determine whether the realm exists or not
- displayName
- enabled
- sslRequired
- registrationAllowed
- loginWithEmailAllowed
- duplicateEmailsAllowed
- resetPasswordAllowed
- editUsernameAllowed
- accessTokenLifespan
- passwordPolicy
- authenticationFlows
- authenticatorConfig
- requiredActions
- bruteForceProtected
- browserFlow
- registrationFlow
- directGrantFlow
- resetCredentialsFlow
- clientAuthenticationFlow
- dockerAuthenticationFlow
- firstBrokerLoginFlow
The format of this file is as close as possible as the one you'll receive by making a partial realm export from keycloak UI.
Here is an exemple of an import file for the helloworld realm :
{
"realm": "helloworld",
"groups": [
{
"name": "adminsysteme",
"path": "/adminsysteme",
"attributes": {
"policy": [
"type_B"
],
"foo": [
"bar"
]
},
"realmRoles": [
"adminsysteme",
"offline_access"
],
"clientRoles": {},
"subGroups": []
}
],
"roles": {
"realm": [
{
"name": "admin",
"description": "Grafana admin Role",
"composite": false,
"clientRole": false,
"containerId": "technique"
},
{
"name": "viewer",
"description": "Grafana viewer Role",
"composite": false,
"clientRole": false,
"containerId": "technique"
},
{
"name": "editor",
"description": "Grafana editor role",
"composite": false,
"clientRole": false,
"containerId": "technique"
},
{
"name": "adminsysteme",
"composite": true,
"composites": {
"client": {
"kubernetes": [
"cluster-admin",
"kubernetes_IHM"
],
"realm-management": [
"query-users",
"query-clients",
"view-realm",
"view-users",
"query-groups",
"view-clients"
]
}
},
"clientRole": false,
"attributes": {}
}
],
"client": {
"kubernetes": [
{
"name": "cluster-admin",
"composite": false,
"clientRole": true,
"attributes": {}
},
{
"name": "cluster-view",
"composite": false,
"clientRole": true,
"attributes": {}
},
{
"name": "admin-monitoring",
"composite": false,
"clientRole": true,
"attributes": {}
},
{
"name": "admin-default",
"composite": false,
"clientRole": true,
"attributes": {}
},
{
"name": "kubernetes_IHM",
"composite": false,
"clientRole": true,
"attributes": {
"tabname": [
"Paas"
]
}
}
]
}
},
"clients": [
{
"clientId": "grafana-oauth",
"name": "",
"description": "",
"rootUrl": "https://grafana.kosmos.wip",
"adminUrl": "https://grafana.kosmos.wip",
"baseUrl": "https://grafana.kosmos.wip",
"enabled": true,
"clientAuthenticatorType": "client-secret",
"secret": "thisismysecretnow",
"redirectUris": [
"https://grafana.kosmos.wip/login/generic_oauth"
],
"protocol": "openid-connect",
"protocolMappers": [
{
"name": "realm roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"multivalued": "true",
"userinfo.token.claim": "true",
"id.token.claim": "true",
"lightweight.claim": "false",
"access.token.claim": "true",
"claim.name": "realm_access.roles",
"jsonType.label": "String"
}
}
],
"fullScopeAllowed": true,
"frontchannelLogout": true,
"directAccessGrantsEnabled": true,
"attributes": {
"oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true",
"post.logout.redirect.uris": "https://grafana.kosmos.wip/login",
"oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false"
},
"defaultClientScopes": [
"web-origins",
"profile",
"offline_access",
"roles",
"email",
"groups"
],
"optionalClientScopes": [
"acr",
"address",
"phone",
"microprofile-jwt",
"basic"
]
},
{
"clientId": "sap",
"name": "",
"description": "",
"rootUrl": "",
"adminUrl": "",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "thisismysecretnow",
"redirectUris": [
"*"
],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": true,
"publicClient": false,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"oidc.ciba.grant.enabled": "false",
"client.secret.creation.time": "1669228910",
"backchannel.logout.session.required": "true",
"oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"protocolMappers": [
{
"name": "Client IP Address",
"protocol": "openid-connect",
"protocolMapper": "oidc-usersessionmodel-note-mapper",
"consentRequired": false,
"config": {
"user.session.note": "clientAddress",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "clientAddress",
"jsonType.label": "String"
}
},
{
"name": "Client ID",
"protocol": "openid-connect",
"protocolMapper": "oidc-usersessionmodel-note-mapper",
"consentRequired": false,
"config": {
"user.session.note": "clientId",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "clientId",
"jsonType.label": "String"
}
},
{
"name": "Client Host",
"protocol": "openid-connect",
"protocolMapper": "oidc-usersessionmodel-note-mapper",
"consentRequired": false,
"config": {
"user.session.note": "clientHost",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "clientHost",
"jsonType.label": "String"
}
},
{
"name": "client roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-client-role-mapper",
"consentRequired": false,
"config": {
"multivalued": "true",
"userinfo.token.claim": "true",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "resource_access.${client_id}.roles",
"jsonType.label": "String"
}
},
{
"name": "realm roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"multivalued": "true",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "realm_access.roles",
"jsonType.label": "String"
}
},
{
"name": "audience-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": false,
"config": {
"included.client.audience": "sap",
"id.token.claim": "false",
"access.token.claim": "true"
}
},
{
"name": "tenant_id",
"protocol": "openid-connect",
"protocolMapper": "oidc-hardcoded-claim-mapper",
"consentRequired": false,
"config": {
"claim.value": "{{ item }}",
"userinfo.token.claim": "false",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "tenant_id",
"access.tokenResponse.claim": "false"
}
}
],
"defaultClientScopes": [
"web-origins",
"acr",
"profile",
"roles",
"email"
],
"optionalClientScopes": [
"address",
"phone",
"offline_access",
"microprofile-jwt"
],
"access": {
"view": true,
"configure": true,
"manage": true
}
},
{
"clientId": "kubernetes",
"name": "kubernetes",
"description": "Kubernetes Dashboard (pf-mon--monitoring)",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "thisismylifenow1A",
"redirectUris": [
"*"
],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"publicClient": false,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"saml.assertion.signature": "false",
"client.secret.creation.time": "1717070951",
"saml.force.post.binding": "false",
"saml.multivalued.roles": "false",
"saml.encrypt": "false",
"backchannel.logout.revoke.offline.tokens": "false",
"saml.server.signature": "false",
"saml.server.signature.keyinfo.ext": "false",
"exclude.session.state.from.auth.response": "false",
"backchannel.logout.session.required": "true",
"saml_force_name_id_format": "false",
"tls.client.certificate.bound.access.tokens": "false",
"saml.client.signature": "false",
"saml.authnstatement": "false",
"display.on.consent.screen": "false",
"saml.onetimeuse.condition": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"protocolMappers": [
{
"name": "groupMapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-group-membership-mapper",
"consentRequired": false,
"config": {
"full.path": "false",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"userinfo.token.claim": "true"
}
},
{
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-client-role-mapper",
"consentRequired": false,
"config": {
"usermodel.clientRoleMapping.rolePrefix": "kast:",
"multivalued": "true",
"userinfo.token.claim": "true",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"jsonType.label": "String",
"usermodel.clientRoleMapping.clientId": "kubernetes"
}
}
],
"defaultClientScopes": [
"web-origins",
"roles",
"profile",
"email"
],
"optionalClientScopes": [
"address",
"phone",
"offline_access",
"microprofile-jwt"
]
}
],
"clientScopes": [
{
"name": "groups",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true"
},
"protocolMappers": [
{
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-group-membership-mapper",
"consentRequired": false,
"config": {
"full.path": "false",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"userinfo.token.claim": "true"
}
}
]
}
],
"scopeMappings": [
{
"clientScope": "groups",
"roles": [
"adminsysteme"
],
"comment": "offline_access de base, modifie pour mon test en groups/adminsysteme"
}
],
"users": [
{
"enabled": true,
"username": "argmin5",
"email": "argmin5@athea.tech",
"emailVerified": true,
"groups": [
"adminsysteme"
],
"firstName": "argo5",
"lastName": "admin",
"attributes": {},
"requiredActions": [],
"realmRoles": [],
"clientRoles": {},
"credentials": [
{
"type": "password",
"value": "foo",
"temporary": false
}
]
},
{
"username": "service-account-sap",
"enabled": true,
"totp": false,
"emailVerified": false,
"serviceAccountClientId": "sap",
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": [],
"clientRoles": {
"realm-management": [
"view-authorization",
"impersonation",
"query-users",
"manage-realm",
"query-clients",
"realm-admin",
"create-client",
"manage-events",
"manage-users",
"query-realms",
"view-identity-providers",
"view-realm",
"manage-authorization",
"view-events",
"manage-identity-providers",
"view-users",
"manage-clients",
"query-groups",
"view-clients"
]
},
"notBefore": 0,
"groups": []
}
],
"authenticationFlows": [
{
"alias": "kosmos-browser",
"description": "Browser limited session authentication",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": false,
"authenticationExecutions": [
{
"authenticator": "auth-cookie",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 0,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "ALTERNATIVE",
"priority": 1,
"flowAlias": "kosmos-browser-auth-session-limit",
"userSetupAllowed": false
}
]
},
{
"alias": "kosmos-browser-auth-session-limit",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": false,
"authenticationExecutions": [
{
"authenticatorFlow": true,
"requirement": "REQUIRED",
"priority": 0,
"flowAlias": "kosmos-browser-auth-session-limit-auth-form",
"userSetupAllowed": false
},
{
"authenticatorConfig": "kosmos-browser-limit",
"authenticator": "user-session-limits",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 1,
"userSetupAllowed": false
}
]
},
{
"alias": "kosmos-browser-auth-session-limit-auth-form",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": false,
"authenticationExecutions": [
{
"authenticator": "identity-provider-redirector",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 0,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "ALTERNATIVE",
"priority": 1,
"flowAlias": "kosmos-browser-auth-session-limit-auth-form-form",
"userSetupAllowed": false
}
]
},
{
"alias": "kosmos-browser-auth-session-limit-auth-form-form",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": false,
"authenticationExecutions": [
{
"authenticator": "auth-username-password-form",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 0,
"userSetupAllowed": false
}
]
}
],
"authenticatorConfig": [
{
"alias": "create unique user config",
"config": {
"require.password.update.after.registration": "false"
}
},
{
"alias": "review profile config",
"config": {
"update.profile.on.first.login": "missing"
}
},
{
"alias": "kosmos-browser-limit",
"config": {
"userClientLimit": "0",
"errorMessage": "Too many session. Please contact you administrator.",
"behavior": "Deny new session",
"userRealmLimit": "10"
}
}
],
"requiredActions": [
{
"alias": "CONFIGURE_TOTP",
"name": "Configure OTP",
"providerId": "CONFIGURE_TOTP",
"enabled": false,
"defaultAction": false,
"priority": 10,
"config": {}
},
{
"alias": "TERMS_AND_CONDITIONS",
"name": "Terms and Conditions",
"providerId": "TERMS_AND_CONDITIONS",
"enabled": false,
"defaultAction": false,
"priority": 20,
"config": {}
},
{
"alias": "UPDATE_PASSWORD",
"name": "Update Password",
"providerId": "UPDATE_PASSWORD",
"enabled": true,
"defaultAction": false,
"priority": 30,
"config": {}
},
{
"alias": "UPDATE_PROFILE",
"name": "Update Profile",
"providerId": "UPDATE_PROFILE",
"enabled": true,
"defaultAction": false,
"priority": 40,
"config": {}
},
{
"alias": "VERIFY_EMAIL",
"name": "Verify Email",
"providerId": "VERIFY_EMAIL",
"enabled": true,
"defaultAction": false,
"priority": 50,
"config": {}
},
{
"alias": "delete_account",
"name": "Delete Account",
"providerId": "delete_account",
"enabled": false,
"defaultAction": false,
"priority": 60,
"config": {}
},
{
"alias": "webauthn-register",
"name": "Webauthn Register",
"providerId": "webauthn-register",
"enabled": true,
"defaultAction": false,
"priority": 70,
"config": {}
},
{
"alias": "webauthn-register-passwordless",
"name": "Webauthn Register Passwordless",
"providerId": "webauthn-register-passwordless",
"enabled": true,
"defaultAction": false,
"priority": 80,
"config": {}
},
{
"alias": "update_user_locale",
"name": "Update User Locale",
"providerId": "update_user_locale",
"enabled": true,
"defaultAction": false,
"priority": 1000,
"config": {}
},
{
"alias": "VERIFY_PROFILE",
"name": "Verify Profile",
"providerId": "VERIFY_PROFILE",
"enabled": false,
"defaultAction": true,
"priority": 10,
"config": {}
}
],
"browserFlow": "kosmos-browser",
"registrationFlow": "registration",
"directGrantFlow": "direct grant",
"resetCredentialsFlow": "reset credentials",
"clientAuthenticationFlow": "clients",
"dockerAuthenticationFlow": "docker auth"
}