Установить PostgreSQL версии 15 по инструкции с официального сайта: https://www.postgresql.org/download
Выполнить тонкую настройку в postgresql.conf по рекомендациям с https://www.pgconfig.org, введя выделенные ресурсы, а так же привести значение шифрования пароля к password_encryption = scram-sha-256 или md5.
Выполнить настройку файла pg_hba.conf, указав:
<type> <database> <user> <address> <method>
где:
type - параметр, указывающий тип подключения (local, host, hostssl, hostnossl, hostgssenc, hostnogssenc)
database - параметр, указывающий к какой БД разрешено подключаться, так же может быть all
user- параметр, указывающий каким пользователем можно подключаться, так же может быть all
address - параметр, указывающий c какого IP адреса или подсети можно подключаться, так же может быть *
method - параметр, указывающий тип шифрования, в нашем случае scram-sha-256 или md5, смотря какой тип был указан в postgresql.conf
Перезапустить службу PostgreSQL
systemctl restart postgresql-15.service
Переключиться в пользователя postgres и создать роль и необходимые базы на сервере:
sudo su - postgres
psql
CREATE ROLE m2 WITH SUPERUSER LOGIN PASSWORD 'superPassw0rd';
CREATE DATABASE m2 WITH OWNER m2;
CREATE DATABASE keycloak WITH OWNER m2;
\c m2;
CREATE SCHEMA m2;
exit
Для установки потребуется программное обеспечение для автоматизации развёртывания и управления приложениями в среде контейнеризации - Docker. Установить, для вашей платформы, можно по инструкции https://docs.docker.com/engine/install/ или любым другим способом, также, необходимым пакетом будет являться docker-compose.
Все необходимые образы будут переданы. Чтобы их загрузить необходимо выполнить команду:
docker load -i <image_name>.tar
mkdir -p /opt/semanticiam && cd $_
FROM nexus.sdi-solution.ru/infra/keycloak:25.0.0-core AS builder
# Configure postgres database vendor
ENV KC_DB=postgres
ENV KC_FEATURES="token-exchange,scripts,preview"
ENV KC_FEATURES_DISABLED="organization"
WORKDIR /opt/keycloak
COPY kc-m2-provider.json providers/kc-m2-provider.json
# COPY sdi.keytab sdi.keytab
RUN /opt/keycloak/bin/kc.sh build --health-enabled=true --metrics-enabled=true
FROM nexus.sdi-solution.ru/infra/keycloak:25.0.0-core AS final
LABEL image.version=25.0.0
COPY --from=builder /opt/keycloak/ /opt/keycloak/
# https://github.com/keycloak/keycloak/issues/19185#issuecomment-1480763024
USER root
RUN sed -i '/disabledAlgorithms/ s/ SHA1,//' /etc/crypto-policies/back-ends/java.config
USER keycloak
RUN /opt/keycloak/bin/kc.sh show-config
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
[INPUT]
Name forward
Listen 0.0.0.0
Port 24224
Tag_Prefix kcEvent.
[OUTPUT]
Name opensearch
Match kcEvent.<wf_instance_name>
Host <opensearch_ip>
Port <opensearch_port>
HTTP_User <user>
HTTP_Passwd <password>
Index user_journal
Generate_ID On
Suppress_Type_Name On
Logstash_Format Off
wf_instance_name - имя. обычно соответствует названию проекта
opensearch_ip - ip адрес сервера opensearch
opensearch_port - порт сервера opensearch
user - пользователь opensearch (admin)
password - пароль пользователя opensearch (admin)
{
"realms": {
"<realm_name>": {
"clientIds": [
"<front_client>",
"<back_client>"
],
"backend": "<semantic_uri>",
"useSpnego": <true/false>
}
},
"flbHost": "<fluent_ip>",
"flbPort": 24222
}
realm_name - название реалма в Keycloak
front_client - имя front клиента, такое же указать и в скрипте создания реалма
back_client - имя back клиента, такое же указать и в скрипте создания реалма
semantic_uri - адрес Semantic
fluent_ip - IP адрес fluent-bit
useSpnego - включает/выключает видимость кнопки войти через Windows
services:
keycloak:
container_name: keycloak
build:
context: .
command: ['start', '--optimized', '--spi-required-action-signal-m2-auth-settings=/opt/keycloak/providers/kc-m2-provider.json', '--spi-events-listener-m2-event-listener-settings=/opt/keycloak/providers/kc-m2-provider.json', '--spi-storage-m2-db-user-federation-settings=/opt/keycloak/providers/kc-m2-provider.json']
environment:
JAVA_OPTS_APPEND: -Dkeycloak.profile.feature.upload_scripts=enabled -agentlib:jdwp=transport=dt_socket,address=keycloak:8787,server=y,suspend=n
KC_DB: postgres
KC_DB_URL: ""
KC_DB_USERNAME:
KC_DB_PASSWORD:
KC_HOSTNAME:
# KC_HOSTNAME_PORT: 8080
KC_HOSTNAME_URL:
# KC_HTTP_RELATIVE_PATH: /
# KC_HOSTNAME_ADMIN_URL:
KC_HTTP_ENABLED: true
KC_PROXY_HEADERS: xforwarded
# KC_HOSTNAME_STRICT: false
# KC_HOSTNAME_STRICT_HTTPS: false
# KC_LOG_LEVEL: info
# KC_LOG_LEVEL: debug
KC_METRICS_ENABLED: true
KC_HEALTH_ENABLED: true
KEYCLOAK_ADMIN:
KEYCLOAK_ADMIN_PASSWORD:
ports:
- 9080:8080
- 9787:8787
networks:
- kc
fluent-bit:
container_name: fluent-bit
image: fluent/fluent-bit
ports:
- 24222:24224
volumes:
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf
networks:
- keycloak
networks:
keycloak:
name: keycloak
hostname: указать FQDN, который должен совпадать с KC_HOSTNAME, KC_HOSTNAME_URL
KC_HOSTNAME: указать FQDN, который должен совпадать с hostname, KC_HOSTNAME_URL
KC_DB_URL: "jdbc:postgresql://<DB_IP>:<DB_PORT>/<DB_NAME>" - параметры подключения к БД
KC_DB_USERNAME: Пользователь БД с доступом к бд keycloak
KC_DB_PASSWORD: Пароль пользователя БД с доступом к бд keycloak
KC_HOSTNAME_URL: http:// | https:// - Полный адрес ресурса, по которому будет доступен Keycloak (необходимо добавить DNS запись и конфигурацию в Nginx, чувствительная настройка)
KC_HTTP_RELATIVE_PATH: / (дефолтное значение), раскомментировать и написать нужный location, если нужно повесить на существующую запись, например https://test.sdi-solution.ru/keycloak
KEYCLOAK_ADMIN: Пользователь, который создастся в Keycloak c администраторскими правами
KEYCLOAK_ADMIN_PASSWORD: Пароль пользователя, который создастся в Keycloak c администраторскими правами
docker compose build
docker compose up -d
touch semantic-realm.sh && chmod +x semantic-realm.sh
#!/bin/bash
keycloakURI=
semanticURI=
semanticHTTP=
adminRealm=master
semanticRealm=
adminClient=admin-cli
frontClient=sdi-web-client
backClient=sdi-core-client
backSecret=
mlClient=sdi-ml-client
mlSecret=
username=
userpass=
systemRoles="read,editData,editMetadata,sysAdministration,exportPatterns,viewHistory,manageApplications,editDataWithoutApplications,runReports,rootNodeAccess,readSecurity,manageSecurity,readUserJournal,similaritySearch,editExpirables,sudo,viceSetup"
# Get bearer token for other Web API calls
token=$(curl --silent -X POST "${keycloakURI}/realms/${adminRealm}/protocol/openid-connect/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data "client_id=${adminClient}" \
--data "username=${username}" \
--data "password=${userpass}" \
--data "grant_type=password" | jq -r .access_token)
# Pass token for create a predefined realm for Semantic use
curl -X POST "${keycloakURI}/admin/realms" \
--header "Authorization: Bearer ${token}" \
--header "Content-Type: application/json" \
--data '{
"id": "'"${semanticRealm}"'",
"realm": "'"${semanticRealm}"'",
"loginTheme": "semantic-mdm",
"notBefore": 0,
"defaultSignatureAlgorithm": "RS256",
"revokeRefreshToken": false,
"refreshTokenMaxReuse": 0,
"accessTokenLifespan": 300,
"accessTokenLifespanForImplicitFlow": 900,
"ssoSessionIdleTimeout": 1800,
"ssoSessionMaxLifespan": 36000,
"ssoSessionIdleTimeoutRememberMe": 0,
"ssoSessionMaxLifespanRememberMe": 0,
"offlineSessionIdleTimeout": 2592000,
"offlineSessionMaxLifespanEnabled": false,
"offlineSessionMaxLifespan": 5184000,
"accessCodeLifespan": 60,
"accessCodeLifespanUserAction": 300,
"accessCodeLifespanLogin": 1800,
"actionTokenGeneratedByAdminLifespan": 43200,
"actionTokenGeneratedByUserLifespan": 300,
"enabled": true,
"sslRequired": "external",
"registrationAllowed": false,
"registrationEmailAsUsername": false,
"rememberMe": false,
"verifyEmail": false,
"loginWithEmailAllowed": false,
"duplicateEmailsAllowed": true,
"resetPasswordAllowed": false,
"editUsernameAllowed": false,
"bruteForceProtected": false,
"permanentLockout": false,
"maxTemporaryLockouts": 0,
"maxFailureWaitSeconds": 900,
"minimumQuickLoginWaitSeconds": 60,
"waitIncrementSeconds": 60,
"quickLoginCheckMilliSeconds": 1000,
"maxDeltaTimeSeconds": 43200,
"failureFactor": 30,
"passwordPolicy": "m2-password-policy",
"eventsListeners": [
"m2-event-listener",
"jboss-logging"
],
"requiredActions": [
{
"alias": "CONFIGURE_TOTP",
"name": "Configure OTP",
"providerId": "CONFIGURE_TOTP",
"enabled": true,
"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": false,
"defaultAction": false,
"priority": 50,
"config": {}
},
{
"alias": "delete_account",
"name": "Delete Account",
"providerId": "delete_account",
"enabled": false,
"defaultAction": false,
"priority": 60,
"config": {}
},
{
"alias": "CONFIGURE_RECOVERY_AUTHN_CODES",
"name": "Recovery Authentication Codes",
"providerId": "CONFIGURE_RECOVERY_AUTHN_CODES",
"enabled": true,
"defaultAction": false,
"priority": 70,
"config": {}
},
{
"alias": "UPDATE_EMAIL",
"name": "Update Email",
"providerId": "UPDATE_EMAIL",
"enabled": true,
"defaultAction": false,
"priority": 70,
"config": {}
},
{
"alia