Skip to content

Commit

Permalink
feat: Assign realm-admin role to service account user and test client…
Browse files Browse the repository at this point in the history
… connection with Keycloak.
  • Loading branch information
viniciusdc committed Oct 6, 2024
1 parent dd0147f commit 858fb5b
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 47 deletions.
19 changes: 19 additions & 0 deletions .github/dockerfiles/Dockerfile.keycloak
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM quay.io/keycloak/keycloak:latest as builder

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true

# Configure a database vendor
ENV KC_DB=postgres

WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:latest
COPY --from=builder /opt/keycloak/ /opt/keycloak/


ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
44 changes: 44 additions & 0 deletions .github/dockerfiles/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
version: '3.8'

services:
postgres:
image: postgres:latest
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: keycloak
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- keycloak-network

keycloak:
build:
context: .
dockerfile: Dockerfile.keycloak
environment:
KC_HOSTNAME: localhost
KC_HOSTNAME_PORT: 8080
KC_HOSTNAME_STRICT_BACKCHANNEL: false
KC_HTTP_ENABLED: true
KC_HOSTNAME_STRICT_HTTPS: false
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: keycloak
command:
- start-dev
ports:
- "8080:8080"
depends_on:
- postgres
networks:
- keycloak-network

volumes:
postgres_data:

networks:
keycloak-network:
64 changes: 48 additions & 16 deletions .github/scripts/setup_workflow.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import json
import os
import time

from keycloak import KeycloakAdmin

# Environment variables
KEYCLOAK_SERVER_URL = os.environ.get(
"KEYCLOAK_SERVER_URL", "http://localhost:8080/auth/"
)
KEYCLOAK_SERVER_URL = os.environ.get("KEYCLOAK_SERVER_URL", "http://localhost:8080/")
KEYCLOAK_ADMIN_USERNAME = os.environ.get("KEYCLOAK_ADMIN_USERNAME", "admin")
KEYCLOAK_ADMIN_PASSWORD = os.environ.get("KEYCLOAK_ADMIN_PASSWORD", "admin")

KEYCLOAK_REALM = os.environ.get("KEYCLOAK_REALM", "test")
KEYCLOAK_CLIENT_ID = os.environ.get("KEYCLOAK_CLIENT_ID", "my-client")
KEYCLOAK_CLIENT_SECRET = os.environ.get("KEYCLOAK_CLIENT_SECRET", "my-client-secret")
KEYCLOAK_CLIENT_ID = os.environ.get("KEYCLOAK_CLIENT_ID", "test-client")
KEYCLOAK_CLIENT_SECRET = os.environ.get("KEYCLOAK_CLIENT_SECRET", "test-client-secret")

# Initialize Keycloak Admin client
keycloak_admin = KeycloakAdmin(
server_url=KEYCLOAK_SERVER_URL,
username=KEYCLOAK_ADMIN_USERNAME,
password=KEYCLOAK_ADMIN_PASSWORD,
realm_name="master",
verify=True,
verify=False,
)

# Wait for Keycloak server to be available
Expand All @@ -40,7 +40,7 @@
print(f"Realm '{KEYCLOAK_REALM}' created.")

# Switch to the new realm
keycloak_admin.realm_name = KEYCLOAK_REALM
keycloak_admin.connection.realm_name = KEYCLOAK_REALM

# Check if the client exists
clients = keycloak_admin.get_clients()
Expand Down Expand Up @@ -71,15 +71,47 @@
service_account_user = keycloak_admin.get_client_service_account_user(client_id)
service_account_user_id = service_account_user["id"]

# Get realm-admin role
roles = keycloak_admin.get_realm_roles()
realm_admin_role = next((role for role in roles if role["name"] == "realm-admin"), None)
# Get realm-management client ID
realm_management_client_id = keycloak_admin.get_client_id("realm-management")
realm_admin_role_id = keycloak_admin.get_client_role_id(
client_id=realm_management_client_id, role_name="realm-admin"
)

realm_admin_role = keycloak_admin.get_role_by_id(role_id=realm_admin_role_id)

# Check if the role is already assigned to the service account user
assigned_roles = keycloak_admin.get_client_role_members(
client_id=realm_management_client_id,
role_name="realm-admin",
)
role_already_assigned = any(
role["id"] == service_account_user_id for role in assigned_roles
)

if realm_admin_role:
# Assign realm-admin role to the service account
keycloak_admin.assign_realm_roles(
user_id=service_account_user_id, roles=[realm_admin_role]
if not role_already_assigned:
# Assign the realm-admin role to the service account user
keycloak_admin.assign_client_role(
user_id=service_account_user_id,
client_id=realm_management_client_id,
roles=[realm_admin_role],
)
print("Assigned 'realm-admin' role to the service account.")
print("Assigned 'realm-admin' role to the service account user.")
else:
print("realm-admin role not found.")
print("'realm-admin' role is already assigned to the service account user.")

# Test client connection
try:
keycloak_admin_test = KeycloakAdmin(
server_url=KEYCLOAK_SERVER_URL,
realm_name=KEYCLOAK_REALM,
client_id=KEYCLOAK_CLIENT_ID,
client_secret_key=KEYCLOAK_CLIENT_SECRET,
verify=False,
)
print("Connected to the client using service account.")
except Exception as e:
raise Exception("Could not connect to the client.") from e

# Get users info from the realm
users = keycloak_admin.get_users()
print(json.dumps(users, indent=2))
90 changes: 59 additions & 31 deletions .github/workflows/test_keycloak_integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,57 @@ on:
jobs:
test:
runs-on: ubuntu-latest
services:
keycloak:
image: quay.io/keycloak/keycloak:22.0.1
ports:
- 8080:8080
options: >-
--health-cmd "curl -f http://localhost:8080/auth/realms/master || exit 1"
--health-interval 10s
--name keycloak
-e start
env:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Build Keycloak Docker image
run: docker build -t keycloak-custom -f .github/dockerfiles/Dockerfile.keycloak .

- name: Create Docker network
run: docker network create test-network

- name: Install test dependencies
- name: Start Postgres container
run: |
python -m pip install --upgrade pip
pip install pytest python-keycloak
docker run -d \
--name postgres \
--network test-network \
-e POSTGRES_DB=keycloak \
-e POSTGRES_USER=keycloak \
-e POSTGRES_PASSWORD=keycloak \
postgres:latest
- name: Wait for Postgres to be ready
run: |
echo "Waiting for Postgres..."
for i in {1..10}; do
if docker exec postgres pg_isready -U keycloak; then
echo "Postgres is ready."
break
else
echo "Postgres not ready yet..."
sleep 5
fi
done
- name: Start Keycloak container
run: |
docker run -d \
--name keycloak \
--network test-network \
-p 8080:8080 \
-e KC_HOSTNAME=localhost \
-e KC_HOSTNAME_PORT=8080 \
-e KC_HOSTNAME_STRICT_BACKCHANNEL=false \
-e KC_HTTP_ENABLED=true \
-e KC_HOSTNAME_STRICT_HTTPS=false \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
-e KC_DB=postgres \
-e KC_DB_URL=jdbc:postgresql://postgres/keycloak \
-e KC_DB_USERNAME=keycloak \
-e KC_DB_PASSWORD=keycloak \
keycloak-custom
- name: Wait for Keycloak to be ready
run: |
Expand All @@ -49,23 +74,26 @@ jobs:
fi
done
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest python-keycloak
- name: Set up Keycloak realm and client
run: python scripts/setup_keycloak.py
env:
KEYCLOAK_SERVER_URL: http://localhost:8080/auth/
KEYCLOAK_SERVER_URL: http://localhost:8080/
KEYCLOAK_ADMIN_USERNAME: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KEYCLOAK_REALM: test
KEYCLOAK_CLIENT_ID: my-client
KEYCLOAK_CLIENT_SECRET: my-client-secret

- name: Install backup-restore server
run: |
pip install -e .
- name: Start service for backup-restore server
run: |
backup-restore --standalone &
- name: Run tests
run: pytest tests/keycloak/
# - name: Run tests
# run: pytest tests/

0 comments on commit 858fb5b

Please sign in to comment.