Skip to content

Commit

Permalink
chore: update keycloak to version 26
Browse files Browse the repository at this point in the history
  • Loading branch information
shreddedbacon committed Dec 27, 2024
1 parent f425c21 commit 3cebb17
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 29 deletions.
54 changes: 43 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ UPSTREAM_TAG ?= latest
# edge is the most current merged change
BUILD_DEPLOY_IMAGE_TAG ?= edge

# UI_IMAGE_REPO and UI_IMAGE_TAG are an easy way to override the UI image used
# UI_IMAGE_REPO = uselagoon/ui
UI_IMAGE_TAG = pr-307

# SSHPORTALAPI_IMAGE_REPO and SSHPORTALAPI_IMAGE_TAG are an easy way to override the ssh portal api image used in the local stack lagoon-core
SSHPORTALAPI_IMAGE_REPO = shreddedbacon/ssh-portal-api
SSHPORTALAPI_IMAGE_TAG = latest

# SSHTOKEN_IMAGE_REPO and SSHTOKEN_IMAGE_TAG are an easy way to override the ssh token image used in the local stack lagoon-core
SSHTOKEN_IMAGE_REPO = shreddedbacon/ssh-token
SSHTOKEN_IMAGE_TAG = latest

# SSHPORTAL_IMAGE_REPO and SSHPORTAL_IMAGE_TAG are an easy way to override the ssh portal image used in the local stack lagoon-remote
# SSHPORTAL_IMAGE_REPO =
# SSHPORTAL_IMAGE_TAG =

# OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGETAG and OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGE_REPOSITORY
# set this to a particular build image if required, defaults to nothing to consume what the chart provides
OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGETAG=
Expand Down Expand Up @@ -346,11 +362,14 @@ logs:
# Start all Lagoon Services
up:
ifeq ($(ARCH), darwin)
IMAGE_REPO=$(CI_BUILD_TAG) docker compose -p $(CI_BUILD_TAG) -f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d
UI_IMAGE_TAG=$(UI_IMAGE_TAG) UI_IMAGE_REPO=$(UI_IMAGE_REPO) \
IMAGE_REPO=$(CI_BUILD_TAG) docker compose -p $(CI_BUILD_TAG) \
-f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d
else
# once this docker issue is fixed we may be able to do away with this
# linux-specific workaround: https://github.com/docker/cli/issues/2290
KEYCLOAK_URL=$$(docker network inspect -f '{{(index .IPAM.Config 0).Gateway}}' bridge):8088 \
UI_IMAGE_TAG=$(UI_IMAGE_TAG) UI_IMAGE_REPO=$(UI_IMAGE_REPO) \
IMAGE_REPO=$(CI_BUILD_TAG) \
docker compose -p $(CI_BUILD_TAG) -f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d
endif
Expand Down Expand Up @@ -380,21 +399,28 @@ local-dev-yarn-stop:

.PHONY: ui-development
ui-development: build-ui-logs-development
IMAGE_REPO=$(CI_BUILD_TAG) docker compose -p $(CI_BUILD_TAG) -f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d api api-db api-sidecar-handler local-api-data-watcher-pusher ui keycloak keycloak-db broker api-redis
UI_IMAGE_TAG=$(UI_IMAGE_TAG) UI_IMAGE_REPO=$(UI_IMAGE_REPO) \
IMAGE_REPO=$(CI_BUILD_TAG) docker compose -p $(CI_BUILD_TAG) \
-f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d api api-db api-sidecar-handler local-api-data-watcher-pusher ui keycloak keycloak-db broker api-redis
$(MAKE) wait-for-keycloak

.PHONY: api-development
api-development: build-ui-logs-development
IMAGE_REPO=$(CI_BUILD_TAG) docker compose -p $(CI_BUILD_TAG) -f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d api api-db api-sidecar-handler local-api-data-watcher-pusher keycloak keycloak-db broker api-redis
UI_IMAGE_TAG=$(UI_IMAGE_TAG) UI_IMAGE_REPO=$(UI_IMAGE_REPO) \
IMAGE_REPO=$(CI_BUILD_TAG) docker compose -p $(CI_BUILD_TAG) \
-f docker-compose.yaml -f docker-compose.local-dev.yaml --compatibility up -d api api-db api-sidecar-handler local-api-data-watcher-pusher keycloak keycloak-db broker api-redis
$(MAKE) wait-for-keycloak

.PHONY: ui-logs-development
ui-logs-development: build-ui-logs-development
IMAGE_REPO=$(CI_BUILD_TAG) COMPOSE_STACK_NAME=$(CI_BUILD_TAG) ADDITIONAL_FLAGS="-f docker-compose.yaml -f docker-compose.local-dev.yaml" ADDITIONAL_SERVICES="ui" $(MAKE) compose-api-logs-development
UI_IMAGE_TAG=$(UI_IMAGE_TAG) UI_IMAGE_REPO=$(UI_IMAGE_REPO) \
IMAGE_REPO=$(CI_BUILD_TAG) COMPOSE_STACK_NAME=$(CI_BUILD_TAG) \
ADDITIONAL_FLAGS="-f docker-compose.yaml -f docker-compose.local-dev.yaml" ADDITIONAL_SERVICES="ui" $(MAKE) compose-api-logs-development

.PHONY: api-logs-development
api-logs-development: build-ui-logs-development
IMAGE_REPO=$(CI_BUILD_TAG) COMPOSE_STACK_NAME=$(CI_BUILD_TAG) ADDITIONAL_FLAGS="-f docker-compose.yaml -f docker-compose.local-dev.yaml" ADDITIONAL_SERVICES="" $(MAKE) compose-api-logs-development
IMAGE_REPO=$(CI_BUILD_TAG) COMPOSE_STACK_NAME=$(CI_BUILD_TAG) \
ADDITIONAL_FLAGS="-f docker-compose.yaml -f docker-compose.local-dev.yaml" ADDITIONAL_SERVICES="" $(MAKE) compose-api-logs-development

# compose-api-logs-development can be consumed by other repositories to start a local api
# supported make variable passthrough are
Expand All @@ -404,7 +430,9 @@ api-logs-development: build-ui-logs-development
# ADDITIONAL_SERVICES - a way to pass through additional services ("ui", "ui ssh", etc..)
.PHONY: compose-api-logs-development
compose-api-logs-development:
docker compose -p $(COMPOSE_STACK_NAME) $(ADDITIONAL_FLAGS) --compatibility up -d $(ADDITIONAL_SERVICES) api api-db api-sidecar-handler actions-handler local-api-data-watcher-pusher keycloak keycloak-db broker api-redis logs2notifications local-minio mailhog
docker compose -p $(COMPOSE_STACK_NAME) $(ADDITIONAL_FLAGS) \
--compatibility up -d $(ADDITIONAL_SERVICES) api api-db api-sidecar-handler actions-handler \
local-api-data-watcher-pusher keycloak keycloak-db broker api-redis logs2notifications local-minio mailhog
$(MAKE) CI_BUILD_TAG=$(COMPOSE_STACK_NAME) wait-for-keycloak

## CI targets
Expand All @@ -417,7 +445,7 @@ STERN_VERSION = v2.6.1
CHART_TESTING_VERSION = v3.11.0
K3D_IMAGE = docker.io/rancher/k3s:v1.31.1-k3s1
TESTS = [nginx,api,features-kubernetes,bulk-deployment,features-kubernetes-2,features-variables,active-standby-kubernetes,tasks,drush,python,gitlab,github,bitbucket,services,workflows]
CHARTS_TREEISH = main
CHARTS_TREEISH = keycloak-tls-updates
CHARTS_REPOSITORY = https://github.com/uselagoon/lagoon-charts.git
#CHARTS_REPOSITORY = ../lagoon-charts
TASK_IMAGES = task-activestandby
Expand Down Expand Up @@ -681,6 +709,10 @@ endif
INSTALL_LAGOON_DEPENDENCIES=false DOCKER_NETWORK=$(DOCKER_NETWORK) \
TESTS=$(TESTS) IMAGE_TAG=$(SAFE_BRANCH_NAME) DISABLE_CORE_HARBOR=true \
HELM=$(HELM) KUBECTL=$(KUBECTL) JQ=$(JQ) \
UI_IMAGE_REPO=$(UI_IMAGE_REPO) UI_IMAGE_TAG=$(UI_IMAGE_TAG) \
SSHPORTALAPI_IMAGE_REPO=$(SSHPORTALAPI_IMAGE_REPO) SSHPORTALAPI_IMAGE_TAG=$(SSHPORTALAPI_IMAGE_TAG) \
SSHTOKEN_IMAGE_REPO=$(SSHTOKEN_IMAGE_REPO) SSHTOKEN_IMAGE_TAG=$(SSHTOKEN_IMAGE_TAG) \
SSHPORTAL_IMAGE_REPO=$(SSHPORTAL_IMAGE_REPO) SSHPORTAL_IMAGE_TAG=$(SSHPORTAL_IMAGE_TAG) \
OVERRIDE_BUILD_DEPLOY_DIND_IMAGE=uselagoon/build-deploy-image:${BUILD_DEPLOY_IMAGE_TAG} \
$$([ $(OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGETAG) ] && echo 'OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGETAG=$(OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGETAG)') \
$$([ $(OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGE_REPOSITORY) ] && echo 'OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGE_REPOSITORY=$(OVERRIDE_BUILD_DEPLOY_CONTROLLER_IMAGE_REPOSITORY)') \
Expand Down Expand Up @@ -778,8 +810,8 @@ k3d/push-images:
k3d/get-lagoon-details:
@export KUBECONFIG="$$(realpath ./kubeconfig.k3d.$(CI_BUILD_TAG))" && \
echo "===============================" && \
echo "Lagoon UI URL: http://lagoon-ui.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io" \
&& echo "Lagoon API URL: http://lagoon-api.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io/graphql" \
echo "Lagoon UI URL: https://lagoon-ui.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io" \
&& echo "Lagoon API URL: https://lagoon-api.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io/graphql" \
&& echo "Lagoon API admin legacy token: $$(docker run \
-e JWTSECRET="$$($(KUBECTL) get secret -n lagoon-core lagoon-core-secrets -o jsonpath="{.data.JWTSECRET}" | base64 --decode)" \
-e JWTAUDIENCE=api.dev \
Expand All @@ -790,7 +822,7 @@ k3d/get-lagoon-details:
&& echo "SSH Core Service: lagoon-ssh.$$($(KUBECTL) -n lagoon-core get services lagoon-core-ssh -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io:$$($(KUBECTL) -n lagoon-core get services lagoon-core-ssh -o jsonpath='{.spec.ports[0].port}')" \
&& echo "SSH Portal Service: lagoon-ssh-portal.$$($(KUBECTL) -n lagoon get services lagoon-remote-ssh-portal -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io:$$($(KUBECTL) -n lagoon get services lagoon-remote-ssh-portal -o jsonpath='{.spec.ports[0].port}')" \
&& echo "SSH Token Service: lagoon-token.$$($(KUBECTL) -n lagoon-core get services lagoon-core-ssh-token -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io:$$($(KUBECTL) -n lagoon-core get services lagoon-core-ssh-token -o jsonpath='{.spec.ports[0].port}')" \
&& echo "Keycloak admin URL: http://lagoon-keycloak.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io/auth" \
&& echo "Keycloak admin URL: https://lagoon-keycloak.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io/auth" \
&& echo "Keycloak admin password: $$($(KUBECTL) get secret -n lagoon-core lagoon-core-keycloak -o jsonpath="{.data.KEYCLOAK_ADMIN_PASSWORD}" | base64 --decode)" \
&& echo "MailPit (email catching service): http://mailpit.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io" \
&& echo "" \
Expand Down Expand Up @@ -832,7 +864,7 @@ k3d/seed-data:
export ROUTER_PATTERN="\$${project}.\$${environment}.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" && \
export SEED_DATA=$$(envsubst < ./local-dev/k3d-seed-data/00-populate-kubernetes.gql | sed 's/"/\\"/g' | sed 's/\\n/\\\\n/g' | awk -F'\n' '{if(NR == 1) {printf $$0} else {printf "\\n"$$0}}') && \
export SEED_DATA_JSON="{\"query\": \"$$SEED_DATA\"}" && \
wget --quiet --header "Content-Type: application/json" --header "Authorization: bearer $${LAGOON_LEGACY_ADMIN}" "http://lagoon-api.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io/graphql" --post-data "$$SEED_DATA_JSON" --content-on-error -O - && \
wget --no-check-certificate --quiet --header "Content-Type: application/json" --header "Authorization: bearer $${LAGOON_LEGACY_ADMIN}" "http://lagoon-api.$$($(KUBECTL) -n ingress-nginx get services ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}').nip.io/graphql" --post-data "$$SEED_DATA_JSON" --content-on-error -O - && \
echo "Loading API seed users" && \
cat ./local-dev/k3d-seed-data/seed-users.sh | $(KUBECTL) -n lagoon-core exec -i $$($(KUBECTL) -n lagoon-core get pods -l app.kubernetes.io/component=lagoon-core-keycloak -o json | $(JQ) -r '.items[0].metadata.name') -- sh -c "cat > /tmp/seed-users.sh" \
&& $(KUBECTL) -n lagoon-core exec -it $$($(KUBECTL) -n lagoon-core get pods -l app.kubernetes.io/component=lagoon-core-keycloak -o json | $(JQ) -r '.items[0].metadata.name') -- bash '/tmp/seed-users.sh' \
Expand Down
2 changes: 1 addition & 1 deletion services/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"license": "MIT",
"dependencies": {
"@lagoon/commons": "4.0.0",
"@s3pweb/keycloak-admin-client-cjs": "^25.0.2",
"@s3pweb/keycloak-admin-client-cjs": "^26.0.0",
"@supercharge/request-ip": "^1.1.2",
"apollo-server-express": "^2.14.2",
"aws-sdk": "^2.378.0",
Expand Down
6 changes: 3 additions & 3 deletions services/keycloak/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM maven:3.8.2-jdk-11 as builder
FROM maven:3.9.9-eclipse-temurin-21-alpine as builder
# build the custom token mapper in builder
COPY custom-mapper/. .
RUN mvn clean compile package
Expand All @@ -17,7 +17,7 @@ COPY javascript /tmp/lagoon-scripts

RUN cd /tmp/lagoon-scripts && zip -r ../lagoon-scripts.jar *

FROM quay.io/keycloak/keycloak:24.0.5
FROM quay.io/keycloak/keycloak:26.0.7
COPY --from=ubi-micro-build /mnt/rootfs /

ARG LAGOON_VERSION
Expand Down Expand Up @@ -87,7 +87,7 @@ COPY entrypoints/default-keycloak-entrypoint.sh /lagoon/entrypoints/99-default-k
COPY startup-scripts /opt/keycloak/startup-scripts
COPY themes/lagoon /opt/keycloak/themes/lagoon
COPY --from=commons /tmp/lagoon-scripts.jar /opt/keycloak/providers/lagoon-scripts.jar
COPY --from=builder /target/custom-protocol-mapper-1.0.0.jar /opt/keycloak/providers/custom-protocol-mapper-1.0.0.jar
COPY --from=builder /target/custom-protocol-mapper-1.1.0.jar /opt/keycloak/providers/custom-protocol-mapper-1.1.0.jar

COPY lagoon-realm-base-import.json /lagoon/seed/lagoon-realm-base-import.json

Expand Down
8 changes: 4 additions & 4 deletions services/keycloak/custom-mapper/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

<groupId>net.cake.keycloak.custom</groupId>
<artifactId>custom-protocol-mapper</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<packaging>jar</packaging>

<properties>
<keycloak.version>17.0.1</keycloak.version>
<keycloak.version>26.0.7</keycloak.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -52,7 +52,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.13.0</version>
<configuration>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<source>1.8</source>
Expand All @@ -62,7 +62,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<version>3.6.0</version>
<executions>
<!-- Run shade goal on package phase -->
<execution>
Expand Down
5 changes: 5 additions & 0 deletions services/keycloak/entrypoints/default-keycloak-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ export KC_HOSTNAME_ADMIN_URL=${KEYCLOAK_FRONTEND_URL}
export KC_DB_POOL_MAX_SIZE=${KEYCLOAK_DS_MAX_POOL_SIZE:-20}
export KC_DB_POOL_MIN_SIZE=${KEYCLOAK_DS_MIN_POOL_SIZE:-0}

# https://www.keycloak.org/docs/latest/upgrading/#admin-bootstrapping-and-recovery
# https://www.keycloak.org/server/bootstrap-admin-recovery
export KC_BOOTSTRAP_ADMIN_USERNAME=$KEYCLOAK_ADMIN_USER
export KC_BOOTSTRAP_ADMIN_PASSWORD=$KEYCLOAK_ADMIN_PASSWORD

KEYCLOAK_USER=$KEYCLOAK_ADMIN_USER KEYCLOAK_PASSWORD=$KEYCLOAK_ADMIN_PASSWORD KEYCLOAK_ADMIN=$KEYCLOAK_ADMIN_USER /lagoon/kc-startup.sh "$@"
8 changes: 7 additions & 1 deletion services/keycloak/entrypoints/kc-startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ shopt -s failglob

/opt/keycloak/startup-scripts/00-configure-lagoon.sh & disown

/opt/keycloak/bin/kc.sh "$@" --features="scripts,token-exchange,admin-fine-grained-authz"
# https://www.keycloak.org/docs/latest/upgrading/#new-hostname-options
# https://www.keycloak.org/server/hostname
# "--hostname-backchannel-dynamic"
# Enables dynamic resolving of backchannel URLs, including hostname, scheme, port and context path.
# Set to true if your application accesses Keycloak via a private network. If set to true, hostname option needs to be specified as a full URL.
/opt/keycloak/bin/kc.sh "$@" --features="scripts,token-exchange,admin-fine-grained-authz" \
--hostname-backchannel-dynamic true --hostname ${KC_HOSTNAME_URL}
18 changes: 9 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -703,10 +703,10 @@
resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c"
integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==

"@keycloak/keycloak-admin-client@25.0.4":
version "25.0.4"
resolved "https://registry.yarnpkg.com/@keycloak/keycloak-admin-client/-/keycloak-admin-client-25.0.4.tgz#2ec46bab133cc807df78ffd7ca7bba47ec8ed000"
integrity sha512-mZVFwly7cHZq1XpvJrrOutU0qrUbGo8NUdpb7PS4309x8yG2a4/WyZfh2lgiopBRQ6R/b24RsuHa4GetQPqT+g==
"@keycloak/keycloak-admin-client@26.0.6":
version "26.0.6"
resolved "https://registry.yarnpkg.com/@keycloak/keycloak-admin-client/-/keycloak-admin-client-26.0.6.tgz#b2ac56de7f4251c8a6a938745843e98000498646"
integrity sha512-pZmaSAyg+LwQ3qnZF+01ZkURpcoEdLAloUK5KOZjE9jyNd86EHdx98/XmTYaJIuQ6ydMXxTWWc5Grq18H+PvJQ==
dependencies:
camelize-ts "^3.0.0"
url-join "^5.0.0"
Expand Down Expand Up @@ -926,12 +926,12 @@
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==

"@s3pweb/keycloak-admin-client-cjs@^25.0.2":
version "25.0.4"
resolved "https://registry.yarnpkg.com/@s3pweb/keycloak-admin-client-cjs/-/keycloak-admin-client-cjs-25.0.4.tgz#925aa0f780233992e44d09a1efbfcbf4718f924a"
integrity sha512-0qQYvmftr4rZKO1JuDq077odNwQ8rS/FGlvBOSOoncvM2i7HljEHvMcsAHR3gNrOkawVlPoYwA+zZdtHICIU4A==
"@s3pweb/keycloak-admin-client-cjs@^26.0.0":
version "26.0.6"
resolved "https://registry.yarnpkg.com/@s3pweb/keycloak-admin-client-cjs/-/keycloak-admin-client-cjs-26.0.6.tgz#49b81da9980d2d3d058a616c8677d64d08a43a34"
integrity sha512-cF4SZcxj/CUK0hZ1dHmyPjVI1BcLvz7u6S8e9YUfqy7wweZScIl1/VpxPgfA9aaLCAcE6kAv++BjcQcvxzkmSg==
dependencies:
"@keycloak/keycloak-admin-client" "25.0.4"
"@keycloak/keycloak-admin-client" "26.0.6"

"@sinclair/typebox@^0.27.8":
version "0.27.8"
Expand Down

0 comments on commit 3cebb17

Please sign in to comment.