diff --git a/docs/install-candig.md b/docs/install-candig.md index 787b18e3e..4ffc87409 100644 --- a/docs/install-candig.md +++ b/docs/install-candig.md @@ -344,8 +344,6 @@ cp -i etc/env/example.env .env LOCAL_IP_ADDR=xxx.xx.x.x # change OS VENV_OS=arm64mac -# change keycloak -KEYCLOAK_BASE_IMAGE=quay.io/c3genomics/keycloak:${KEYCLOAK_VERSION}.arm64 ``` Edit /etc/hosts on the machine (`sudo nano /etc/hosts`): diff --git a/etc/env/example.env b/etc/env/example.env index a3814786d..c0afd1273 100644 --- a/etc/env/example.env +++ b/etc/env/example.env @@ -175,23 +175,18 @@ CACHE_TIME=0 # keycloak service -KEYCLOAK_VERSION=16.1.1 -#KEYCLOAK_BASE_IMAGE=quay.io/c3genomics/keycloak:${KEYCLOAK_VERSION}.arm64 -KEYCLOAK_BASE_IMAGE=quay.io/keycloak/keycloak:${KEYCLOAK_VERSION} +KEYCLOAK_VERSION=24.0.0 KEYCLOAK_REALM=candig KEYCLOAK_CLIENT_ID=local_candig KEYCLOAK_LOGIN_REDIRECT_PATH=/auth/login KEYCLOAK_PORT=8080 -KEYCLOAK_CONTAINER_PORT=8080 -KEYCLOAK_HOST=0.0.0.0 KEYCLOAK_PUBLIC_PROTO=http KEYCLOAK_PRIVATE_PROTO=http KEYCLOAK_ENABLE_PROXY=false KEYCLOAK_PUBLIC_URL=${KEYCLOAK_PUBLIC_PROTO}://${CANDIG_AUTH_DOMAIN}:${KEYCLOAK_PORT} KEYCLOAK_PUBLIC_URL_PROD=${KEYCLOAK_PUBLIC_PROTO}://${CANDIG_AUTH_DOMAIN} -KEYCLOAK_PRIVATE_URL=${KEYCLOAK_PRIVATE_PROTO}://${CANDIG_AUTH_DOMAIN}:${KEYCLOAK_CONTAINER_PORT} +KEYCLOAK_PRIVATE_URL=${KEYCLOAK_PRIVATE_PROTO}://${CANDIG_AUTH_DOMAIN}:${KEYCLOAK_PORT} KEYCLOAK_REALM_URL=${KEYCLOAK_PUBLIC_URL}/auth/realms/${KEYCLOAK_REALM} - KEYCLOAK_GENERATE_TEST_USER=1 # query service diff --git a/lib/keycloak/Dockerfile b/lib/keycloak/Dockerfile deleted file mode 100644 index 34290e575..000000000 --- a/lib/keycloak/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -ARG BASE_IMAGE -FROM ${BASE_IMAGE} - -COPY ./configuration_templates/* /opt/jboss/keycloak/standalone/ \ No newline at end of file diff --git a/lib/keycloak/client_setup.sh b/lib/keycloak/client_setup.sh new file mode 100644 index 000000000..734d37a11 --- /dev/null +++ b/lib/keycloak/client_setup.sh @@ -0,0 +1,38 @@ +# This script creates and configures a client within a Keycloak realm + +echo +echo -e "${BLUE}Creating client: $KEYCLOAK_CLIENT_ID${DEFAULT}" + +CREATE_OUTPUT=$(KCADM create clients -r "$KEYCLOAK_REALM" \ + -s clientId="$KEYCLOAK_CLIENT_ID" \ + -s enabled=true \ + -s protocol=openid-connect \ + -s publicClient=false \ + -s clientAuthenticatorType=client-secret \ + -s standardFlowEnabled=true \ + -s directAccessGrantsEnabled=true \ + -s 'redirectUris=["'"$TYK_LOGIN_TARGET_URL$KEYCLOAK_LOGIN_REDIRECT_PATH"'"]' \ + -s 'webOrigins=["'"$TYK_LOGIN_TARGET_URL"'"]' 2>&1) +# uncomment the line beblow to see the output +# echo $CREATE_OUTPUT + +# Extract the client ID from the output +CLIENT_ID=$(echo $CREATE_OUTPUT | grep -oE '[0-9a-fA-F-]{36}') + +# Create client scopes +SCOPE_NAME="${KEYCLOAK_CLIENT_ID}-audience" +CREATE_OUTPUT=$(KCADM create clients/$CLIENT_ID/protocol-mappers/models -r $KEYCLOAK_REALM \ + -s name=$SCOPE_NAME \ + -s protocol=openid-connect \ + -s protocolMapper=oidc-audience-mapper \ + -s config="{\"included.client.audience\" : \"$KEYCLOAK_CLIENT_ID\",\"id.token.claim\" : \"true\",\"access.token.claim\" : \"true\"}" 2>&1) +# uncomment the line beblow to see the output +# echo $CREATE_OUTPUT + +# EXPORT: Get the client secret and save it to secrets +CLIENT_SECRET=$(KCADM get clients/"$CLIENT_ID"/client-secret -r "$KEYCLOAK_REALM" | jq -r '.value') +echo "$CLIENT_SECRET" > tmp/secrets/keycloak-client-$KEYCLOAK_CLIENT_ID-secret + +# EXPORT: Encode the Keycloak client ID in base64 and save it to secrets +KEYCLOAK_CLIENT_ID_64=$(echo -n "${KEYCLOAK_CLIENT_ID}" | base64) +echo "$KEYCLOAK_CLIENT_ID_64" > "tmp/secrets/keycloak-client-${KEYCLOAK_CLIENT_ID}-id-64" diff --git a/lib/keycloak/configuration_templates/application-users.properties b/lib/keycloak/configuration_templates/application-users.properties deleted file mode 100644 index 24889c3f3..000000000 --- a/lib/keycloak/configuration_templates/application-users.properties +++ /dev/null @@ -1,25 +0,0 @@ -# -# Properties declaration of users for the realm 'ApplicationRealm' which is the default realm -# for application services on a new installation. -# -# This includes the following protocols: remote ejb, remote jndi, web, remote jms -# -# Users can be added to this properties file at any time, updates after the server has started -# will be automatically detected. -# -# The format of this realm is as follows: - -# username=HEX( MD5( username ':' realm ':' password)) -# -# A utility script is provided which can be executed from the bin folder to add the users: - -# - Linux -# bin/add-user.sh -# -# - Windows -# bin\add-user.bat -# -#$REALM_NAME=ApplicationRealm$ This line is used by the add-user utility to identify the realm name already used in this file. -# -# The following illustrates how an admin user could be defined, this -# is for illustration only and does not correspond to a usable password. -# -#admin=2a0923285184943425d1f53ddd58ec7a diff --git a/lib/keycloak/configuration_templates/logging.properties b/lib/keycloak/configuration_templates/logging.properties deleted file mode 100644 index 3e7aeb1bf..000000000 --- a/lib/keycloak/configuration_templates/logging.properties +++ /dev/null @@ -1,70 +0,0 @@ -# -# JBoss, Home of Professional Open Source. -# Copyright 2013, Red Hat, Inc., and individual contributors -# as indicated by the @author tags. See the copyright.txt file in the -# distribution for a full listing of individual contributors. -# -# This is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of -# the License, or (at your option) any later version. -# -# This software is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this software; if not, write to the Free -# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA, or see the FSF site: http://www.fsf.org. -# - -# Additional loggers to configure (the root logger is always configured) -loggers=com.arjuna,jacorb,org.jboss.as.config,org.apache.tomcat.util.modeler,sun.rmi,jacorb.config - -logger.level=INFO -logger.handlers=CONSOLE,FILE - -logger.com.arjuna.level=WARN -logger.com.arjuna.useParentHandlers=true - -logger.jacorb.level=WARN -logger.jacorb.useParentHandlers=true - -logger.org.jboss.as.config.level=DEBUG -logger.org.jboss.as.config.useParentHandlers=true - -logger.org.apache.tomcat.util.modeler.level=WARN -logger.org.apache.tomcat.util.modeler.useParentHandlers=true - -logger.sun.rmi.level=WARN -logger.sun.rmi.useParentHandlers=true - -logger.jacorb.config.level=ERROR -logger.jacorb.config.useParentHandlers=true - -handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler -handler.CONSOLE.level=INFO -handler.CONSOLE.formatter=COLOR-PATTERN -handler.CONSOLE.properties=autoFlush,target -handler.CONSOLE.autoFlush=true -handler.CONSOLE.target=SYSTEM_OUT - -handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler -handler.FILE.level=ALL -handler.FILE.formatter=PATTERN -handler.FILE.properties=autoFlush,append,fileName,suffix -handler.FILE.constructorProperties=fileName,append -handler.FILE.autoFlush=true -handler.FILE.append=true -handler.FILE.fileName=${org.jboss.boot.log.file:boot.log} -handler.FILE.suffix=.yyyy-MM-dd - -formatter.COLOR-PATTERN=org.jboss.logmanager.formatters.PatternFormatter -formatter.COLOR-PATTERN.properties=pattern -formatter.COLOR-PATTERN.pattern=%K{level}%d{HH\:mm\:ss,SSS} %-5p [%c] (%t) %s%E%n - -formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter -formatter.PATTERN.properties=pattern -formatter.PATTERN.pattern=%d{yyyy-MM-dd HH\:mm\:ss,SSS} %-5p [%c] (%t) %s%E%n diff --git a/lib/keycloak/configuration_templates/mgmt-users.properties b/lib/keycloak/configuration_templates/mgmt-users.properties deleted file mode 100644 index 1eb477657..000000000 --- a/lib/keycloak/configuration_templates/mgmt-users.properties +++ /dev/null @@ -1,27 +0,0 @@ -# -# Properties declaration of users for the realm 'ManagementRealm' which is the default realm -# for new installations. Further authentication mechanism can be configured -# as part of the in standalone.xml. -# -# Users can be added to this properties file at any time, updates after the server has started -# will be automatically detected. -# -# By default the properties realm expects the entries to be in the format: - -# username=HEX( MD5( username ':' realm ':' password)) -# -# A utility script is provided which can be executed from the bin folder to add the users: - -# - Linux -# bin/add-user.sh -# -# - Windows -# bin\add-user.bat -# -#$REALM_NAME=ManagementRealm$ This line is used by the add-user utility to identify the realm name already used in this file. -# -# On start-up the server will also automatically add a user $local - this user is specifically -# for local tools running against this AS installation. -# -# The following illustrates how an admin user could be defined, this -# is for illustration only and does not correspond to a usable password. -# -#admin=2a0923285184943425d1f53ddd58ec7a diff --git a/lib/keycloak/configuration_templates/standalone-ha.xml b/lib/keycloak/configuration_templates/standalone-ha.xml deleted file mode 100644 index 35da18455..000000000 --- a/lib/keycloak/configuration_templates/standalone-ha.xml +++ /dev/null @@ -1,636 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - h2 - - sa - sa - - - - jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE - h2 - - sa - sa - - - - - org.h2.jdbcx.JdbcDataSource - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - auth - - - classpath:${jboss.home.dir}/providers/* - - - master - 900 - - 2592000 - true - true - ${env.KEYCLOAK_WELCOME_THEME:keycloak} - ${jboss.home.dir}/themes - - - - - - - - - - - - - jpa - - - basic - - - - - - - - - - - - - - - - - - - default - - - - - - - - ${keycloak.jta.lookup.provider:jboss} - - - - - - - - - - - ${keycloak.x509cert.lookup.provider:default} - - - - ${keycloak.hostname.provider:request} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/keycloak/configuration_templates/standalone.xml b/lib/keycloak/configuration_templates/standalone.xml deleted file mode 100644 index 461ac9497..000000000 --- a/lib/keycloak/configuration_templates/standalone.xml +++ /dev/null @@ -1,573 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - h2 - - sa - sa - - - - jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE - h2 - - sa - sa - - - - - org.h2.jdbcx.JdbcDataSource - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - auth - - classpath:${jboss.home.dir}/providers/* - - master - 900 - - 2592000 - true - true - ${jboss.home.dir}/themes - - - - - - - - - - - - - jpa - - - basic - - - - - - - - - - - - - - - - - - - default - - - - - - - - ${keycloak.jta.lookup.provider:jboss} - - - - - - - - - - - ${keycloak.x509cert.lookup.provider:default} - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/keycloak/credential_loader.sh b/lib/keycloak/credential_loader.sh new file mode 100755 index 000000000..747081ddf --- /dev/null +++ b/lib/keycloak/credential_loader.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Load credentials from secrets +export KEYCLOAK_ADMIN=$(< /run/secrets/keycloak-admin-user) +export KEYCLOAK_ADMIN_PASSWORD=$(< /run/secrets/keycloak-admin-password) + +exec /opt/keycloak/bin/kc.sh "$@" \ No newline at end of file diff --git a/lib/keycloak/docker-compose.yml b/lib/keycloak/docker-compose.yml index 76cf005f2..b85f7ed86 100644 --- a/lib/keycloak/docker-compose.yml +++ b/lib/keycloak/docker-compose.yml @@ -1,31 +1,30 @@ services: keycloak: - build: - context: ${PWD}/lib/keycloak - args: - #- BASE_IMAGE=candig/keycloak:${KEYCLOAK_VERSION} - - BASE_IMAGE=${KEYCLOAK_BASE_IMAGE} + image: keycloak/keycloak:${KEYCLOAK_VERSION} labels: - "candigv2=keycloak" - command: [ "-b", "${KEYCLOAK_HOST}", "-Dkeycloak.migration.strategy=IGNORE_EXISTING" ] - ports: - - "${KEYCLOAK_CONTAINER_PORT}:8080" - extra_hosts: - - "${CANDIG_DOMAIN}:${LOCAL_IP_ADDR}" volumes: - - keycloak-data:/opt/jboss/keycloak/standalone + - ${PWD}/lib/keycloak/credential_loader.sh:/opt/keycloak/credential_loader.sh + - keycloak-data:/opt/keycloak/data environment: - - KEYCLOAK_USER_FILE=/run/secrets/keycloak-admin-user - - KEYCLOAK_PASSWORD_FILE=/run/secrets/keycloak-admin-password - - PROXY_ADDRESS_FORWARDING=${KEYCLOAK_ENABLE_PROXY} - #- KEYCLOAK_FRONTEND_URL=${KEYCLOAK_PUBLIC_URL_PROD}/auth + KC_HOSTNAME: ${CANDIG_DOMAIN} + PROXY_ADDRESS_FORWARDING: ${KEYCLOAK_ENABLE_PROXY} + KC_HTTP_RELATIVE_PATH: /auth + KC_HEALTH_ENABLED: true + KC_METRICS_ENABLED: true + QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: true + # KEYCLOAK_FRONTEND_URL: ${KEYCLOAK_PUBLIC_URL_PROD}/auth secrets: - - source: keycloak-admin-user - target: /run/secrets/keycloak-admin-user - - source: keycloak-admin-password - target: /run/secrets/keycloak-admin-password + - keycloak-admin-user + - keycloak-admin-password + ports: + - "${KEYCLOAK_PORT}:8080" + extra_hosts: + - "${CANDIG_DOMAIN}:${LOCAL_IP_ADDR}" + entrypoint: ["/bin/sh", "-c"] + command: ["/opt/keycloak/credential_loader.sh start-dev"] healthcheck: - test: [ "CMD", "curl", "-f", "http://0.0.0.0:8080" ] + test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/8080;echo -e \"GET /auth/health HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n\" >&3;grep \"HTTP/1.1 200 OK\" <&3"] interval: 30s - timeout: 20s - retries: 3 + timeout: 10s + retries: 3 \ No newline at end of file diff --git a/lib/keycloak/realm_setup.sh b/lib/keycloak/realm_setup.sh new file mode 100644 index 000000000..300d41150 --- /dev/null +++ b/lib/keycloak/realm_setup.sh @@ -0,0 +1,19 @@ +# This script creates and configures a realm within Keycloak + +echo +echo -e "${BLUE}Creating realm: $KEYCLOAK_REALM${DEFAULT}" + +CREATE_OUTPUT=$(KCADM create realms -s realm="$KEYCLOAK_REALM" -s enabled=true 2>&1) +# uncomment the line beblow to see the output +# echo $CREATE_OUTPUT + +KCADM update events/config -r ${KEYCLOAK_REALM} \ +-s adminEventsEnabled=true \ +-s adminEventsDetailsEnabled=true \ +-s eventsEnabled=true \ +-s eventsExpiration=259200 \ +-s 'enabledEventTypes=["CLIENT_DELETE", "CLIENT_DELETE_ERROR", "CLIENT_INFO", "CLIENT_INFO_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "CLIENT_LOGIN", "CLIENT_LOGIN_ERROR", "CLIENT_REGISTER", "CLIENT_REGISTER_ERROR", "CLIENT_UPDATE", "CLIENT_UPDATE_ERROR", "CODE_TO_TOKEN", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "CUSTOM_REQUIRED_ACTION_ERROR", "EXECUTE_ACTIONS", "EXECUTE_ACTIONS_ERROR", "EXECUTE_ACTION_TOKEN", "EXECUTE_ACTION_TOKEN_ERROR", "FEDERATED_IDENTITY_LINK", "FEDERATED_IDENTITY_LINK_ERROR", "GRANT_CONSENT", "GRANT_CONSENT_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR", "IDENTITY_PROVIDER_LINK_ACCOUNT", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "IDENTITY_PROVIDER_LOGIN", "IDENTITY_PROVIDER_LOGIN_ERROR", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "IDENTITY_PROVIDER_RESPONSE", "IDENTITY_PROVIDER_RESPONSE_ERROR", "IDENTITY_PROVIDER_RETRIEVE_TOKEN", "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR", "IMPERSONATE", "IMPERSONATE_ERROR", "INTROSPECT_TOKEN", "INTROSPECT_TOKEN_ERROR", "INVALID_SIGNATURE", "INVALID_SIGNATURE_ERROR", "LOGIN", "LOGIN_ERROR", "LOGOUT", "LOGOUT_ERROR", "PERMISSION_TOKEN", "PERMISSION_TOKEN_ERROR", "REFRESH_TOKEN", "REFRESH_TOKEN_ERROR", "REGISTER", "REGISTER_ERROR", "REGISTER_NODE", "REGISTER_NODE_ERROR", "REMOVE_FEDERATED_IDENTITY", "REMOVE_FEDERATED_IDENTITY_ERROR", "REMOVE_TOTP", "REMOVE_TOTP_ERROR", "RESET_PASSWORD", "RESET_PASSWORD_ERROR", "RESTART_AUTHENTICATION", "RESTART_AUTHENTICATION_ERROR", "REVOKE_GRANT", "REVOKE_GRANT_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "SEND_RESET_PASSWORD", "SEND_RESET_PASSWORD_ERROR", "SEND_VERIFY_EMAIL", "SEND_VERIFY_EMAIL_ERROR", "TOKEN_EXCHANGE", "TOKEN_EXCHANGE_ERROR", "UNREGISTER_NODE", "UNREGISTER_NODE_ERROR", "UPDATE_CONSENT", "UPDATE_CONSENT_ERROR", "UPDATE_EMAIL", "UPDATE_EMAIL_ERROR", "UPDATE_PASSWORD", "UPDATE_PASSWORD_ERROR", "UPDATE_PROFILE", "UPDATE_PROFILE_ERROR", "UPDATE_TOTP", "UPDATE_TOTP_ERROR", "USER_INFO_REQUEST", "USER_INFO_REQUEST_ERROR", "VALIDATE_ACCESS_TOKEN", "VALIDATE_ACCESS_TOKEN_ERROR", "VERIFY_EMAIL", "VERIFY_EMAIL_ERROR"]' + +# EXPORT: Get the realm public key and save it to secrets +KEYCLOAK_PUBLIC_KEY=$(curl ${KEYCLOAK_PUBLIC_URL}/auth/realms/${KEYCLOAK_REALM} -k 2>/dev/null | jq -r '.public_key') +echo "$KEYCLOAK_PUBLIC_KEY" > tmp/secrets/keycloak-public-key \ No newline at end of file