Syntax highlighting of 6d08fec ~( devops/keycloak)
= Keycloak = <<TableOfContents()>> == Установка и запуск == После перебора различных вариантов установки и запуска Keycloak самым комфортным оказался 'docker-compose'. Пример конфигурации Keycloak с letsencrypt, базой данных PostgreSQL и автоматическим бекапированием на S3: {{{#!highlight yaml --- services: proxy: image: traefik:v3.3 command: - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.myresolver.acme.tlschallenge=true" - "--certificatesresolvers.myresolver.acme.email=mail@example.com" # <--------------------------- - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" ports: - target: 80 published: 80 protocol: tcp mode: host - target: 443 published: 443 protocol: tcp mode: host volumes: - /var/run/docker.sock:/var/run/docker.sock - ./letsencrypt:/letsencrypt keycloak: image: quay.io/keycloak/keycloak:26.0.1 restart: unless-stopped command: start ports: - "127.0.0.1:8080:8080" environment: KC_PROXY_ADDRESS_FORWARDING: "true" KC_HOSTNAME_STRICT: "false" KC_HOSTNAME_STRICT_HTTPS: "false" KC_HOSTNAME: keycloak.example.com # <--------------------------- KC_HTTP_ENABLED: "true" KC_PROXY_HEADERS: xforwarded KEYCLOAK_ADMIN: tmpadmin KEYCLOAK_ADMIN_PASSWORD: secret # <--------------------------- # --- KC_DB: postgres KC_DB_URL: jdbc:postgresql://postgres:5432/kc KC_DB_USERNAME: db_username # <--------------------------- KC_DB_PASSWORD: db_secret # <--------------------------- # --- labels: - "traefik.http.routers.kc.rule=Host(`keycloak.example.com`)" # <--------------------------- - "traefik.http.routers.kc.service=kc" - "traefik.http.routers.kc.entrypoints=websecure" - "traefik.http.routers.kc.tls.certresolver=myresolver" - "traefik.http.services.kc.loadbalancer.server.port=8080" postgres: image: postgres:16 environment: POSTGRES_USER: db_username # <--------------------------- POSTGRES_PASSWORD: db_password # <--------------------------- POSTGRES_DB: kc PGDATA: /var/lib/postgresql/data/pgdata ports: - "127.0.0.1:5432:5432" volumes: - postgresql_data:/var/lib/postgresql/data/pgdata deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 256M command: > postgres -c max_connections=1000 -c shared_buffers=256MB -c effective_cache_size=768MB -c maintenance_work_mem=64MB -c checkpoint_completion_target=0.7 -c wal_buffers=16MB -c default_statistics_target=100 healthcheck: test: [ "CMD-SHELL", "pg_isready -U db_username -d kc" ] # <--------------------------- interval: 30s timeout: 10s retries: 5 restart: unless-stopped tty: true stdin_open: true backup: image: eeshugerman/postgres-backup-s3:16 environment: SCHEDULE: '@daily' BACKUP_KEEP_DAYS: 14 S3_ENDPOINT: https://s3.endpoint.com # <--------------------------- S3_REGION: my-region # <--------------------------- S3_ACCESS_KEY_ID: access_key # <--------------------------- S3_SECRET_ACCESS_KEY: secret_key # <--------------------------- S3_BUCKET: bucket_name # <--------------------------- S3_PREFIX: backups # <--------------------------- POSTGRES_HOST: postgres POSTGRES_DATABASE: kc POSTGRES_USER: db_username # <--------------------------- POSTGRES_PASSWORD: db_password # <--------------------------- volumes: postgresql_data: {} }}} == Интеграция == === Grafana === Источники: . [[ https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/generic-oauth/ ]] . [[ https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/keycloak/ ]] . [[ https://stackoverflow.com/questions/68741412/grafana-generic-oauth-role-assignment ]] Интеграция с Grafana осуществляется в соответствии с документацией. Однако, необходимо учитывать особенность: Grafana осуществляет поиск ролей в 'id_token', а не 'access_token'. По умолчанию, роли пользователя не попадают в id_token, поэтому надо подкрутить конфигурацию клиента - [[ https://stackoverflow.com/questions/68741412/grafana-generic-oauth-role-assignment ]]. === SSH === Пример конфигурации, которая позволяет предоставлять административный доступ к серверу через `ssh` путем назначения роли пользователю или группе. План: 1. настраиваем сервер 2. устанавливаем расширение в Keycloak На этапе настройки сервера устанавливаем [[https://github.com/kha7iq/kc-ssh-pam | kc-ssh-pam]]. В процессе установки можно внести ряд дополнений: Запрещаем дальнейшие действия в случае неудачной проверки пользователя в Keycloak. Это может быть полезным, если локальный пользователь с таким же именем уже существует на сервере или в Keycloak такого пользователя. В таком случае, пользователь сможет зайти под локальной учетной записью, что не является предпочтительным. {{{ # --- вместо auth sufficient pam_exec.so expose_authtok log=/var/log/kc-ssh-pam.log /opt/kc-ssh-pam/kc-ssh-pam auth optional pam_script.so # --- использовать auth [success=2 default=ignore] pam_exec.so expose_authtok log=/var/log/kc-ssh-pam.log /opt/kc-ssh-pam/kc-ssh-pam auth optional pam_script.so auth requisite pam_deny.so }}} В скрипте `/usr/share/libpam-script/pam_script_auth` добавляем строку {{{#!highlight bash adduser $PAM_USER sudo }}} чтобы новый пользователь сразу добавлялся в группу `sudo`. Также, здесь необходимо отключить пароль для `sudo`. {{{#!highlight bash sudo visudo # --- вместо %sudo ALL=(ALL:ALL) ALL # --- используем %sudo ALL=NOPASSWD: ALL }}} На втором этапе устанавливаем расширение [[https://github.com/sventorben/keycloak-restrict-client-auth | keycloak-restrict-client-auth ]] для Keycloak. Это расширение нам требуется для ограничение доступа к Realm клиенту, созданному на предыдущем этапе. "Из коробки" (на сколько понимаю) Keycloak не предоставляет такую возможность. Установку выполняем по [[https://github.com/sventorben/keycloak-restrict-client-auth/blob/main/README.md | README.md ]] для ''Client Role based'' режима. Здесь можно использовать более простой вариант аутентификации {{devops/keycloak/ssh-flow|SSH authorization flow | width=50%}} Кроме того, требуется указать новый способ аутентификации в настройках клиента ''ssh-login'': Clients > ssh-login > Advanced > Authentication flow overrides > Direct Grant Flow По итогу получаем, что при назначении роли `restricted-access` пользователю или группе предоставляется `ssh` доступ с ''sudo'' к преднастроенным серверам. == Рецепты == === Восстанавливаем доступ администратора === Для восстановления пароля требуется доступ к серверу, на котором установлен Keycloak. Создаем временного администратора {{{#!highlight bash bin/kc.sh bootstrap-admin user }}} Далее: 1. заходим под временным администратором, 2. сбрасываем пароль, 3. заходим под администратором, 4. удаляем временного администратора. === Как получить токен === В целях отладки можно выполнить `curl` запрос к Keycloak и получить токен {{{#!highlight bash curl -d "grant_type=password" \ -d "scope=openid" \ -d "client_id=client_id" \ -d "client_secret=client_secret" \ -d "username=username" \ -d "password=secret" \ https://keycloak.example.com/realms/REALM_NAME/protocol/openid-connect/token | jq . }}}
