Skip to content

Commit

Permalink
Merge pull request #3828 from uselagoon/local-dev-keycloak-helper-scr…
Browse files Browse the repository at this point in the history
…ipts

chore: add some seed scripts for keycloak
  • Loading branch information
tobybellwood authored Oct 31, 2024
2 parents 4e0d239 + dfd2c41 commit b1314fe
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 19 deletions.
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,21 @@ wait-for-keycloak:
&& docker compose -p $(CI_BUILD_TAG) exec -it keycloak bash '/tmp/seed-users.sh' \
&& echo "You will be able to log in with these seed user email addresses and the passwords will be the same as the email address" \
&& echo "eg. [email protected] has the password [email protected]" \
&& echo "" \
&& echo "If you want to create an example SSO identity provider and example user, run make compose/example-sso" \
&& echo "If you want to configure simple webauthn browswer flow, run make compose/configure-webauthn" \
&& echo ""

.PHONY: compose/example-sso
compose/example-sso:
@docker compose -p $(CI_BUILD_TAG) cp ./local-dev/k3d-seed-data/seed-example-sso.sh keycloak:/tmp/seed-example-sso.sh \
&& docker compose -p $(CI_BUILD_TAG) exec -it keycloak bash '/tmp/seed-example-sso.sh'

.PHONY: compose/configure-webauthn
compose/configure-webauthn:
@docker compose -p $(CI_BUILD_TAG) cp ./local-dev/k3d-seed-data/configure-webauthn.sh keycloak:/tmp/configure-webauthn.sh \
&& docker compose -p $(CI_BUILD_TAG) exec -it keycloak bash '/tmp/configure-webauthn.sh'

# Define a list of which Lagoon Services are needed for running any deployment testing
main-test-services = actions-handler broker api-sidecar-handler logs2notifications api api-db api-redis api-sidecar-handler keycloak keycloak-db ssh auth-server local-git local-api-data-watcher-pusher local-minio

Expand Down Expand Up @@ -734,8 +747,23 @@ k3d/seed-data:
&& $(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' \
&& echo "You will be able to log in with these seed user email addresses and the passwords will be the same as the email address" \
&& echo "eg. [email protected] has the password [email protected]" \
&& echo "" \
&& echo "If you want to create an example SSO identity provider and example user, run make k3d/example-sso" \
&& echo "If you want to configure simple webauthn browswer flow, run make k3d/configure-webauthn" \
&& echo ""

.PHONY: k3d/example-sso
k3d/example-sso:
@export KUBECONFIG="$$(realpath ./kubeconfig.k3d.$(CI_BUILD_TAG))" && \
cat ./local-dev/k3d-seed-data/seed-example-sso.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-example-sso.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-example-sso.sh'

.PHONY: k3d/configure-webauthn
k3d/configure-webauthn:
@export KUBECONFIG="$$(realpath ./kubeconfig.k3d.$(CI_BUILD_TAG))" && \
cat ./local-dev/k3d-seed-data/configure-webauthn.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/configure-webauthn.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/configure-webauthn.sh'

# Use k3d/port-forwards to create local ports for the UI (6060), API (7070) and Keycloak (8080). These ports will always
# log in the foreground, so perform this command in a separate window/terminal.
.PHONY: k3d/port-forwards
Expand Down
30 changes: 15 additions & 15 deletions local-dev/k3d-seed-data/00-populate-kubernetes.gql
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,6 @@ mutation PopulateApi {
id
}

LagoonDemoToGroup: addGroupsToProject(
input: {
project: {
name: "lagoon-demo"
}
groups: [
{
name: "lagoon-demo-group"
}
]
}
) {
id
}

UserExampleGuestGroup: addUserToGroup(
input: {
user: {
Expand Down Expand Up @@ -433,6 +418,21 @@ mutation PopulateApi {
id
}

LagoonDemoToGroup: addGroupsToProject(
input: {
project: {
name: "lagoon-demo"
}
groups: [
{
name: "lagoon-demo-group"
}
]
}
) {
id
}

# Add mailhub service
UIProject1Envvar: addOrUpdateEnvVariableByName(
input: {
Expand Down
55 changes: 55 additions & 0 deletions local-dev/k3d-seed-data/configure-webauthn.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

CONFIG_PATH=/tmp/kcadm.config
/opt/keycloak/bin/kcadm.sh config credentials --config $CONFIG_PATH --server http://localhost:8080/auth --user $KEYCLOAK_ADMIN_USER --password $KEYCLOAK_ADMIN_PASSWORD --realm master

if [ "$(/opt/keycloak/bin/kcadm.sh get authentication/flows -r "lagoon" --fields id,alias --config $CONFIG_PATH | jq -r '.[] | select(.alias==("Browser-Webauthn")) | .id')" == "" ]; then
echo "Creating browser flow for webauthn"
/opt/keycloak/bin/kcadm.sh create authentication/flows -r "lagoon" -s alias="Browser-Webauthn" -s providerId=basic-flow -s topLevel=true -s builtIn=false --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn/executions/execution -i -b '{"provider" : "auth-cookie"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"ALTERNATIVE"}' -r "lagoon" --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn/executions/execution -i -b '{"provider" : "auth-spnego"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"DISABLED"}' -r "lagoon" --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn/executions/execution -i -b '{"provider" : "identity-provider-redirector"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"ALTERNATIVE"}' -r "lagoon" --config $CONFIG_PATH

FLOW_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn/executions/flow -i -r "lagoon" -b '{"alias" : "Browser-Webauthn-Forms" , "type" : "basic-flow"}' --config $CONFIG_PATH)
EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh get authentication/flows/Browser-Webauthn/executions -r "lagoon" --fields id,flowId,alias --config $CONFIG_PATH | jq -r '.[] | select(.flowId==("'"$FLOW_ID"'")) | .id')
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn/executions -r "lagoon" -b '{"id":"'"$EXECUTION_ID"'","requirement":"ALTERNATIVE"}' --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn-Forms/executions/execution -i -b '{"provider" : "auth-username-password-form"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn-Forms/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"REQUIRED"}' -r "lagoon" --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn-Forms/executions/execution -i -b '{"provider" : "webauthn-authenticator"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn-Forms/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"ALTERNATIVE"}' -r "lagoon" --config $CONFIG_PATH

FLOW_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn-Forms/executions/flow -i -r "lagoon" -b '{"alias" : "Browser-Webauthn-Conditional2FA" , "type" : "basic-flow"}' --config $CONFIG_PATH)
EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh get authentication/flows/Browser-Webauthn-Forms/executions -r "lagoon" --fields id,flowId,alias --config $CONFIG_PATH | jq -r '.[] | select(.flowId==("'"$FLOW_ID"'")) | .id')
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn-Forms/executions -r "lagoon" -b '{"id":"'"$EXECUTION_ID"'","requirement":"CONDITIONAL"}' --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn-Conditional2FA/executions/execution -i -b '{"provider" : "conditional-user-configured"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn-Conditional2FA/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"REQUIRED"}' -r "lagoon" --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn-Conditional2FA/executions/execution -i -b '{"provider" : "webauthn-authenticator"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn-Conditional2FA/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"ALTERNATIVE"}' -r "lagoon" --config $CONFIG_PATH

EXECUTION_ID=$(/opt/keycloak/bin/kcadm.sh create authentication/flows/Browser-Webauthn-Conditional2FA/executions/execution -i -b '{"provider" : "auth-otp-form"}' -r "lagoon" --config $CONFIG_PATH)
/opt/keycloak/bin/kcadm.sh update authentication/flows/Browser-Webauthn-Conditional2FA/executions -b '{"id":"'"$EXECUTION_ID"'","requirement":"ALTERNATIVE"}' -r "lagoon" --config $CONFIG_PATH

echo "Set the realm to use the new webauthn browserflow"
/opt/keycloak/bin/kcadm.sh update realms/lagoon -s browserFlow=Browser-Webauthn --config $CONFIG_PATH

echo "Delete webauthn-register required action, this may report resource not found which is fine to ignore"
/opt/keycloak/bin/kcadm.sh delete authentication/required-actions/webauthn-register -r lagoon --config $CONFIG_PATH

echo "Register webauthn-register required action"
/opt/keycloak/bin/kcadm.sh create authentication/register-required-action -r lagoon \
-s providerId=webauthn-register \
-s name="Webauthn Register" \
--config $CONFIG_PATH
else
echo "Browser flow for webauthn already created"
fi
75 changes: 75 additions & 0 deletions local-dev/k3d-seed-data/seed-example-sso.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash

CONFIG_PATH=/tmp/kcadm.config

# login to keycloak
/opt/keycloak/bin/kcadm.sh config credentials \
--config $CONFIG_PATH --server http://localhost:8080/auth \
--user $KEYCLOAK_ADMIN_USER --password $KEYCLOAK_ADMIN_PASSWORD \
--realm master

if /opt/keycloak/bin/kcadm.sh get realms/sso --config $CONFIG_PATH > /dev/null; then
echo "Realm sso is already created, skipping"
exit 0
fi

# create the SSO realm
echo "Creating new sso realm"
/opt/keycloak/bin/kcadm.sh create realms --config $CONFIG_PATH -s realm=sso -s enabled=true

# Create a user in the SSO realm

echo "Creating user and configuring password for [email protected]"
/opt/keycloak/bin/kcadm.sh create users -r sso \
-s [email protected] \
-s firstName=sso \
-s lastName=user \
-s username=sso-user \
-s enabled=true \
-o --fields id,username \
--config $CONFIG_PATH

# Set the password for the SSO user
/opt/keycloak/bin/kcadm.sh set-password \
--config $CONFIG_PATH \
--username sso-user \
-p [email protected] \
--target-realm sso

# create the SSO realm OIDC client
echo "Creating example client in sso realm"
echo '{"clientId": "sso-oidc-client", "publicClient": false, "webOrigins": ["*"], "redirectUris": ["*"]}' | /opt/keycloak/bin/kcadm.sh create clients --config $CONFIG_PATH -r sso -f -
CLIENT_ID=$(/opt/keycloak/bin/kcadm.sh get -r sso clients?clientId=sso-oidc-client --config $CONFIG_PATH | jq -r '.[0]["id"]')
echo '{"protocol":"openid-connect","config":{"id.token.claim":"true","access.token.claim":"true","userinfo.token.claim":"true","user.attribute":"lagoon-uid","claim.name":"lagoon.user_id","jsonType.label":"int","multivalued":""},"name":"Lagoon User ID","protocolMapper":"oidc-usermodel-attribute-mapper"}' | /opt/keycloak/bin/kcadm.sh create -r sso clients/$CLIENT_ID/protocol-mappers/models --config $CONFIG_PATH -f -
/opt/keycloak/bin/kcadm.sh update clients/$CLIENT_ID -s secret=123456789 --config $CONFIG_PATH -r sso


# create the IDP in the Lagoon realm linking to the SSO OIDC client
echo "Creating ssorealm identity provider in lagoon realm"
/opt/keycloak/bin/kcadm.sh create identity-provider/instances -s enabled=true \
-s displayName=ssorealm \
-s alias=ssorealm \
-s providerId=oidc \
-s config.authorizationUrl=${KEYCLOAK_FRONTEND_URL%/}/realms/sso/protocol/openid-connect/auth \
-s config.tokenUrl=http://localhost:8080/auth/realms/sso/protocol/openid-connect/token \
-s config.logoutUrl=${KEYCLOAK_FRONTEND_URL%/}/realms/sso/protocol/openid-connect/logout \
-s config.userInfoUrl=http://localhost:8080/auth/realms/sso/protocol/openid-connect/userinfo \
-s config.issuer=${KEYCLOAK_FRONTEND_URL%/}/realms/sso \
-s config.validateSignature=true \
-s config.pkceEnabled=false \
-s config.clientAuthMethod=client_secret_post \
-s config.clientId=sso-oidc-client \
-s config.clientSecret=123456789 \
-s config.metadataDescriptorUrl=http://localhost:8080/auth/realms/sso/.well-known/openid-configuration \
-s config.jwksUrl=http://localhost:8080/auth/realms/sso/protocol/openid-connect/certs \
-s config.useJwksUrl=true --config $CONFIG_PATH -r lagoon

# create a role mapper that grants any users from the SSO realm as platform-owner
echo "Configuring ssorealm identity provider with platform-owner role mapping"
/opt/keycloak/bin/kcadm.sh create identity-provider/instances/ssorealm/mappers \
-s name=platform-owner \
-s identityProviderMapper=oidc-hardcoded-role-idp-mapper \
-s identityProviderAlias=ssorealm \
-s config.syncMode=FORCE \
-s config.role=platform-owner \
--config $CONFIG_PATH -r lagoon
8 changes: 4 additions & 4 deletions local-dev/k3d-seed-data/seed-users.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ function configure_user_passwords {
for i in ${LAGOON_DEMO_USERS[@]}
do
echo Configuring password for $i
/opt/keycloak/bin/kcadm.sh set-password --config $CONFIG_PATH --username $i -p $i --target-realm Lagoon
/opt/keycloak/bin/kcadm.sh set-password --config $CONFIG_PATH --username $i -p $i --target-realm lagoon
done

for i in ${LAGOON_DEMO_ORG_USERS[@]}
do
echo Configuring password for $i
/opt/keycloak/bin/kcadm.sh set-password --config $CONFIG_PATH --username $i -p $i --target-realm Lagoon
/opt/keycloak/bin/kcadm.sh set-password --config $CONFIG_PATH --username $i -p $i --target-realm lagoon
done
}

function configure_platformowner {
echo Configuring platform owner role
/opt/keycloak/bin/kcadm.sh add-roles --uusername [email protected] --rolename platform-owner --config $CONFIG_PATH --target-realm Lagoon
/opt/keycloak/bin/kcadm.sh add-roles --uusername [email protected] --rolename platform-owner --config $CONFIG_PATH --target-realm lagoon
}

function configure_platformviewer {
echo Configuring platform viewer role
/opt/keycloak/bin/kcadm.sh add-roles --uusername [email protected] --rolename platform-viewer --config $CONFIG_PATH --target-realm Lagoon
/opt/keycloak/bin/kcadm.sh add-roles --uusername [email protected] --rolename platform-viewer --config $CONFIG_PATH --target-realm lagoon
}

function configure_keycloak {
Expand Down

0 comments on commit b1314fe

Please sign in to comment.