General

Installation

wget https://github.com/keycloak/keycloak/releases/download/20.0.3/keycloak-20.0.3.tar.gz -O /tmp/keycloak-20.0.3.tar.gz
sudo tar -zxvf /tmp/keycloak-20.0.3.tar.gz -C /opt/
sudo mv /opt/keycloak-20.0.3/ /opt/keycloak
sudo groupadd keycloak 
sudo useradd -r -g keycloak -d /opt/keycloak -s /sbin/nologin keycloak 
## Keycloak permissions 
sudo chown -R keycloak:keycloak /opt/keycloak 
sudo chmod -R o+rwx /opt/keycloak

# update /opt/keycloak/conf/keycloak.conf as keycloak user
keycloak@idp:~$ ./bin/kc.sh build
keycloak@idp:~$ export KEYCLOAK_ADMIN=admin
keycloak@idp:~$ export KEYCLOAK_ADMIN_PASSWORD=XXXX
keycloak@idp:~$ ./bin/kc.sh

cat <<EOF | sudo tee -a /etc/systemd/system/keycloak.service
[Unit]
Description=Keycloak Application Server
After=syslog.target network.target

[Service]
Type=simple
TimeoutStopSec=0
Restart=on-failure
RestartSec=2s
KillSignal=SIGTERM
KillMode=process
SuccessExitStatus=143
LimitMEMLOCK=infinity
SendSIGKILL=no
WorkingDirectory=/opt/keycloak/
User=keycloak
Group=keycloak
LimitNOFILE=102642
# Default user
Environment=KEYCLOAK_ADMIN=admin
Environment=KEYCLOAK_ADMIN_PASSWORD=XXXX
# Database
Environment=KC_DB=postgres
Environment=KC_DB_PASSWORD=XXXX
Environment=KC_DB_USERNAME=keycloak
Environment=KC_DB_URL=jdbc:postgresql://localhost/keycloak
# Proxy
Environment=KC_PROXY=edge
Environment=KC_HOSTNAME_STRICT=false
ExecStart=/opt/keycloak/bin/kc.sh start --optimized

[Install]
WantedBy=multi-user.target
EOF

sudo apt install postgresql postgresql-contrib -y

sudo -u postgres psql -c "CREATE USER keycloak WITH PASSWORD 'changeme-postgres';"
sudo -u postgres psql -c "CREATE DATABASE keycloak OWNER keycloak;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;"

# keycloak configuration
./bin/kc.sh start --db postgres --db-url-host localhost --db-username keycloak --db-password changeme-postgres
kc.sh start --optimized --db-url-host=localhost --db-username=keycloak --db-password=*******

# sysctcl
root@idp:/etc/sysctl.d# cat 98-keycloak.conf
net.core.wmem_max=26214400
net.core.rmem_max=26214400 

Backup

backup config for specific REALMNAME

bin/standalone.sh -Dkeycloak.migration.action=export -Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file=${REALMNAME}-keycloak-export.json -Djboss.http.port=8888 -Djboss.https.port=9999 -Djboss.management.http.port=7777 [-Dkeycloak.migration.realmName=${REALMNAME}]

backup config for all realms

bin/standalone.sh -Dkeycloak.migration.action=export -Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file=all-realms-keycloak-export.json -Djboss.http.port=8888 -Djboss.https.port=9999 -Djboss.management.http.port=7777`

Integration with ldap

https://codehumsafar.wordpress.com/tag/ldap-with-keycloak/

user federation ldap config

"config" : {
        "pagination" : [ "true" ],
        "fullSyncPeriod" : [ "-1" ],
        "usersDn" : [ "cn=users,cn=accounts,dc=mylabserver,dc=com" ],
        "connectionPooling" : [ "true" ],
        "cachePolicy" : [ "DEFAULT" ],
        "useKerberosForPasswordAuthentication" : [ "false" ],
        "importEnabled" : [ "true" ],
        "enabled" : [ "true" ],
        "bindCredential" : [ "mrxQm1Wo6eu1bxAhAJ7rreMJ" ],
        "changedSyncPeriod" : [ "-1" ],
        "usernameLDAPAttribute" : [ "uid" ],
        "bindDn" : [ "uid=vault,cn=users,cn=accounts,dc=mylabserver,dc=com" ],
        "lastSync" : [ "1585833916" ],
        "vendor" : [ "other" ],
        "uuidLDAPAttribute" : [ "uid" ],
        "allowKerberosAuthentication" : [ "false" ],
        "connectionUrl" : [ "ldap://172.31.28.49:389" ],
        "syncRegistrations" : [ "false" ],
        "authType" : [ "simple" ],
        "customUserSearchFilter" : [ "(uid=*)" ],
        "debug" : [ "false" ],
        "searchScope" : [ "2" ],
        "useTruststoreSpi" : [ "ldapsOnly" ],
        "priority" : [ "0" ],
        "trustEmail" : [ "false" ],
        "userObjectClasses" : [ "inetorgperson" ],
        "rdnLDAPAttribute" : [ "uid" ],
        "editMode" : [ "READ_ONLY" ],
        "validatePasswordPolicy" : [ "false" ],
        "batchSizeForSync" : [ "1000" ]
      }

group mapping - this will result in user/group mapping which is same on ldap and keycloak

### group mapping
https://www.janua.fr/mapping-ldap-group-and-roles-to-redhat-sso-keycloak/
{
          "id" : "45c0f95c-d834-4904-aeac-886957b09d3d",
          "name" : "ldap-group-mapping",
          "providerId" : "group-ldap-mapper",
          "subComponents" : { },
          "config" : {
            "membership.attribute.type" : [ "DN" ],
            "group.name.ldap.attribute" : [ "cn" ],
            "membership.user.ldap.attribute" : [ "uid" ],
            "preserve.group.inheritance" : [ "true" ],
            "groups.dn" : [ "cn=groups,cn=accounts,dc=mylabserver,dc=com" ],
            "mode" : [ "READ_ONLY" ],
            "user.roles.retrieve.strategy" : [ "LOAD_GROUPS_BY_MEMBER_ATTRIBUTE" ],
            "groups.ldap.filter" : [ "(objectclass=ipausergroup)" ],
            "ignore.missing.groups" : [ "false" ],
            "membership.ldap.attribute" : [ "member" ],
            "group.object.classes" : [ "groupOfNames" ],
            "memberof.ldap.attribute" : [ "memberOf" ],
            "drop.non.existing.groups.during.sync" : [ "false" ]
          }

role mapping - this will create roles under realm and map users to specific roles defined one the ldap side

{
          "id" : "57e9dc44-3b46-47f2-8b62-8bc95e03fb40",
          "name" : "ldap-role-mapping",
          "providerId" : "role-ldap-mapper",
          "subComponents" : { },
          "config" : {
            "mode" : [ "READ_ONLY" ],
            "membership.attribute.type" : [ "DN" ],
            "roles.dn" : [ "cn=roles,cn=accounts,dc=computingforgeeks,dc=com" ],
            "user.roles.retrieve.strategy" : [ "GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE" ],
            "membership.user.ldap.attribute" : [ "uid" ],
            "membership.ldap.attribute" : [ "member" ],
            "memberof.ldap.attribute" : [ "memberOf" ],
            "role.name.ldap.attribute" : [ "cn" ],
            "use.realm.roles.mapping" : [ "true" ],
            "roles.ldap.filter" : [ "(objectClass=groupOfNames)" ],
            "role.object.classes" : [ "groupOfNames" ]
          }

Other

Mapping clients

When one create a client mappers are used for token and documents transformation.Based on that info:

  • User Property - it will be copied from ldap (e.g. username,family name,given name,email)
  • User Sessions Note - used by some oidc (e.g. clientid,clientIPaddress,clietnhost)
  • Group Membership - used for ldap-group mapping (e.g. group)
  • Role Name Mapper - used be mapping(or renaming) roles from Realm to be used on specific client.
  • User Realm Role - used to map Realm roles to the ldap user

Client scopes

Under Evaluate one can evaluate generated access token with roles/groups and other metadata per user.

getting access_token and converting it to jwt (json web token) including response via curl

curl -s -X POST -k -d "scope=openid" \
-d "username=${USERNAME}" \
-d "password=${PASSWORD}" \
-d "grant_type=password" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
http://${KEYCLOAK_HOST}:8080/auth/realms/${REALM}/protocol/openid-connect/token | jq '.access_token' | sed 's/[^.]*.\([^.]*\).*/\1/' | base64 -d | jq

An example of the response is:

{
  "exp": 1586444033,
  "iat": 1586443733,
  "jti": "88e1b10d-15b4-41a9-bd69-45ea55aec3de",
  "iss": "http://localhost:8080/auth/realms/computingforgeeks.com",
  "aud": "account",
  "sub": "8b505d1f-82e5-4e8c-8a77-ddf48a9af7ad",
  "typ": "Bearer",
  "azp": "grafana",
  "session_state": "e30ad572-af9e-4aad-942c-a23ae3004b13",
  "acr": "1",
  "allowed-origins": [
    ""
  ],
  "realm_access": {
    "roles": [
      "offline_access",
      "new_admins",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "openid email profile",
  "email_verified": false,
  "role": [
    "offline_access",
    "new_admins",
    "uma_authorization"
  ],
  "name": "new_admin new_admin new_admin",
  "preferred_username": "new_admin",
  "given_name": "new_admin new_admin",
  "family_name": "new_admin",
  "email": "[email protected]",
  "group": [
    "/ipausers",
    "/new_admins"
  ]
}

Run keycloak as docker container

docker run -d -p 18080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev

Docker setup

keycloak:
    image: keycloak-mybuild:20.0.3
    restart: on-failure:5
    container_name: keycloak
    command: start --optimized 
    ports:
      - "8080"
    environment:
      - KC_DB=postgres
      - KC_DB_URL=jdbc:postgresql://postgres:5432/xxxxxxxx
      - KC_DB_USERNAME=xxxxxxxx
      - KC_DB_PASSWORD=xxxxxxxx
      - KEYCLOAK_ADMIN=admin
      - KEYCLOAK_ADMIN_PASSWORD=xxxxxxxx
      - KC_HOSTNAME_STRICT=false
      - KC_HOSTNAME_STRICT_HTTPS=false
      - PROXY_ADDRESS_FORWARDING=true
      - KC_HTTP_RELATIVE_PATH=/auth
      - KC_HTTP_ENABLED=true
      - KC_HTTP_PORT=8080
      - JAVA_OPTS_APPEND="-Dcom.redhat.fips=false"
    depends_on:
      - postgres
    networks:
      - namednetwork

Install in k8s cluster

install keycloak via helm

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install keycloak bitnami/keycloak --set volumePermissions.enabled=true

update pv

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-postgres
spec:
  capacity:
    storage: 8Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  hostPath:
    path: /data

It works as sts but one should add pv and update perm on pv to use 1001:1001 for pv.spec.hostPath.path

References

https://www.keycloak.org/docs/latest/getting_started/
https://github.com/dcm4che/dcm4chee-arc-light/wiki/Getting-OIDC-Access-Token-using-curl
https://codehumsafar.wordpress.com/tag/ldap-with-keycloak/
https://www.janua.fr/using-client-scope-with-redhat-sso-keycloak/
https://www.janua.fr/mapping-ldap-group-and-roles-to-redhat-sso-keycloak/
https://www.doag.org/formes/pubfiles/11145218/2019-NN-Thomas_Darimont-Sichere_Spring-Anwendungen_mit_Keycloak-Praesentation.pdf
https://github.com/thomasdarimont/awesome-keycloak
https://developer.okta.com/blog/2017/07/25/oidc-primer-part-1
https://developer.okta.com/blog/2017/07/25/oidc-primer-part-2
https://developer.okta.com/blog/2017/08/01/oidc-primer-part-3 https://docs.sonarqube.org/latest/instance-administration/authentication/saml/how-to-set-up-keycloak/
https://cloudinfrastructureservices.co.uk/install-keycloak-sso-on-ubuntu-20-04/
https://www.altenburger.io/posts/install_keycloak/
https://www.keycloak.org/server/reverseproxy
https://www.keycloak.org/server/all-config
https://www.keycloak.org/docs/latest/server_admin/index.html
https://www.keycloak.org/getting-started/getting-started-zip
https://github.com/keycloak/keycloak/issues/10357
https://robferguson.org/blog/2020/01/03/keycloak-flowable-and-openldap/
https://github.com/deskoh/keycloak-kerberos
https://medium.com/rahasak/deploy-ldap-directory-service-with-openldap-docker-8d9f438f1216
https://gruchalski.com/posts/2020-09-03-keycloak-with-docker-compose/
https://david.kow.is/2020/10/31/docker-compose-an-openldap-server/
https://robferguson.org/blog/2019/12/24/getting-started-with-keycloak/
https://joostvdg.github.io/blogs/kubernetes-sso-keycloak/#fn:11
https://computingforgeeks.com/run-openldap-server-in-docker-containers/
https://www.janua.fr/ldap-integration-with-keycloak/
https://migueldoctor.medium.com/run-keycloak-locally-using-docker-and-secure-your-apps-in-3-steps-f6c554427e54
https://warlord0blog.wordpress.com/2020/07/22/keycloak-container-set/
https://github.com/osixia/docker-openldap/blob/master/example/docker-compose.yml
http://www.mastertheboss.com/keycloak/keycloak-with-docker/
https://github.com/deskoh/keycloak-kerberos/tree/master/openldap
https://github.com/osixia/docker-openldap/blob/master/example/docker-compose.yml
https://geek-cookbook.funkypenguin.co.nz/docker-swarm/traefik/
https://gruchalski.com/posts/2020-09-03-keycloak-with-docker-compose/
https://github.com/asatrya/keycloak-traefik-tutorial
https://github.com/ibuetler/docker-keycloak-traefik-workshop
https://www.keycloak.org/docs/latest/server_admin/index.html#_user-storage-federation
https://documentation.abas.cloud/en/abas-keycloak/setup-user-federation-ldap.html
https://www.janua.fr/mapping-ldap-group-and-roles-to-redhat-sso-keycloak/
https://codehumsafar.wordpress.com/tag/ldap-with-keycloak/
https://www.soundsessential.com/blog/215-keycloak-17-filemaker-installation-configuration-tutorial-part-4-starting-keycloak-17-next-steps
https://github.com/keycloak/keycloak/issues/10357