Хоть наш тех.отдел и нельзя считать достаточно крупным, но по мере роста количества сервисов стала возникать проблема авторизации в них – Grafana, ArgoCD, Vault, etc. Мы распределяем кластера Kubernetes по следующей схеме – кластер для каждого проекта и каждой среды, это позволяет сперва оттестировать что-то новое на дев среде, потом перетащить на стейдж и уже после внедрять на продакшене. И вот из-за такого подхода количество сервисов стало стремительно расти. Поэтому в качестве Single-Sing-On (SSO) был выбран Keycloak.
Почему Keycloak? Во-первых это opensource проект курируемый RedHat. Во-вторых продукт бесплатный, не скажу, что кто-то ограничивал бюджет, но если есть возможность сэкономить – почему бы и да.
Схема установки была выбрана достаточна простая – базу будем использовать RDS PostgreSQL 13, а сам сервис разместим на EC2 инстансе. От лоадбалансера AWS также решено отказаться – поэтому терменировать сертификат будем на Traefik, который будет так же выступать как reverse-proxy. Из полезного замечу то, что у Traefik есть провайдер Route53, поэтому в нашем случае требуется создать IAM Policy для доступа к зоне в Route53, пример:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"route53:GetChange",
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*",
"arn:aws:route53:::change/*"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": "route53:ListHostedZonesByName",
"Resource": "*"
}
]
}
Собственно для визуализации прикрепляю схему как оно выглядит
Запуск Keycloak
Ниже приведен файл docker-compose для запуска Keycloak, в качестве провайдера для получения сертификата от Let’s Encrypt можно использовать любой доступный из доки Traefik:
version: '3.9'
services:
traefik:
image: traefik:2.6
container_name: traefik
restart: unless-stopped
volumes:
- ./acme.json:/acme.json:rw
- /var/run/docker.sock:/var/run/docker.sock
networks:
- keycloak
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.api.rule=Host(`traefik.${DOMAIN}`)'
- 'traefik.http.routers.api.entrypoints=https'
- 'traefik.http.routers.api.service=api@internal'
- 'traefik.http.routers.api.tls=true'
- 'traefik.http.routers.api.tls.certresolver=route53'
- "traefik.http.middlewares.my-whitelist-in-docker.ipwhitelist.sourcerange=1.1.1.1/32" # we declare our middleware
- "traefik.http.routers.api.middlewares=my-whitelist-in-docker@docker" # we apply our middleware
ports:
- 80:80
- 443:443
command:
- '--api'
- '--providers.docker=true'
- '--experimental.http3=true'
- '--providers.docker.exposedByDefault=false'
- '--entrypoints.http=true'
- '--entrypoints.http.address=:80'
- '--entrypoints.http.http.redirections.entrypoint.to=https'
- '--entrypoints.http.http.redirections.entrypoint.scheme=https'
- '--entrypoints.https=true'
- '--entrypoints.https.address=:443'
- '--certificatesResolvers.route53.acme.storage=/acme.json'
- '--certificatesResolvers.route53.acme.caServer=https://acme-v02.api.letsencrypt.org/directory'
- '--certificatesresolvers.route53.acme.dnschallenge.provider=route53'
- '--certificatesresolvers.route53.acme.dnschallenge.delaybeforecheck=0'
- '--certificatesresolvers.route53.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53'
- '--log=true'
- '--log.level=INFO'
keycloak:
container_name: keycloak
environment:
DB_VENDOR: postgres
DB_ADDR: ${POSTGRESQL_HOST}
DB_DATABASE: ${POSTGRESQL_DB}
DB_USER: ${POSTGRESQL_USER}
DB_PASSWORD: ${POSTGRESQL_PASS}
PROXY_ADDRESS_FORWARDING: "true"
KEYCLOAK_LOGLEVEL: "INFO"
image: jboss/keycloak:${KEYCLOAK_VERSION}
restart: unless-stopped
command: ["-b", "0.0.0.0", "-Dkeycloak.profile.feature.docker=enabled"]
networks:
- keycloak
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.keycloak.rule=Host(`${DOMAIN}`)'
- 'traefik.http.routers.keycloak.entrypoints=https'
- 'traefik.http.routers.keycloak.tls=true'
- 'traefik.http.routers.keycloak.tls.certresolver=route53'
- 'traefik.http.routers.keycloak.service=keycloak'
- 'traefik.http.services.keycloak.loadbalancer.server.port=8080'
networks:
keycloak:
Из правок данного файла, нужно изменить на свои параметры 1.1.1.1/32 – прописываем свои IP для доступа в дашборд Traefik
Также в директории с файлом docker-compose.yaml создаем файл .env в котором прописываем данные подключения к базе, домен для Traefik
KEYCLOAK_VERSION=16.1.1 # Указываем актуальную версию контейнера
PORT_KEYCLOAK=8080 # Порт Keycloak
POSTGRESQL_USER=your_keycloak_user
POSTGRESQL_PASS=strong_db_password_here
POSTGRESQL_DB=your_keycloak_db
POSTGRESQL_HOST=database_host
DOMAIN=my-auth-domain.net # Домен для Traefik
Если необходимо развернуть локально и базу, то стоит добавить в docker-compose.yaml
...
postgres:
image: postgres:13
restart: unless-stopped
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${POSTGRESQL_DB}
POSTGRES_USER: ${POSTGRESQL_USER}
POSTGRES_PASSWORD: ${POSTGRESQL_PASS}
networks:
- keycloak
volumes:
pgdata:
...
Запустим данный проект командой:
docker-compose -f docker-compose.yaml up -d
Создание учетной записи администратора
После запуска docker-compose, мы можем перейти на страницу авторизации Keycloak, для этого перейдем по адресу https://YOUR_DOMAIN/auth/
Если запуска прошел успешно, то мы должны увидеть следующее:
Как указано на скриншоте – для дальнейшего использования понадобится создать пользователя-администратора, для этого необходимо выполнить команду:
docker exec keycloak /opt/jboss/keycloak/bin/add-user-keycloak.sh -u YOUR_USERNAME -p YOUR_PASSWORD
docker restart keycloak
где YOUR_USERNAME имя администратора, а YOUR_PASSWORD его пароль.
Полезные ссылки
Настройка Grafana:
https://janikvonrotz.ch/2020/08/27/grafana-oauth-with-keycloak-and-how-to-validate-a-jwt-token/
Настройка ArgoCD:
https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/keycloak/
Be First to Comment