Skip to content

Commit

Permalink
Keycloak realm with groups (#2002)
Browse files Browse the repository at this point in the history
* added a group and mapper to keycloak w/ burnettk

* accept an internal uri to keycloak w/ burnettk

* pyl w/ burnettk

* the only time we ever use internal arg to open_id_endpoint_for_name we want it True

* protect users of openid urls from internal urls

* allow port 8000/8001 for docker and avoid public urls when using requests again

* allow 8001 frontend in docker compose post logout redirect url

---------

Co-authored-by: jasquat <[email protected]>
Co-authored-by: burnettk <[email protected]>
  • Loading branch information
3 people authored Jul 29, 2024
1 parent b8c7aa9 commit d2c5c27
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_docker_images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ on:
push:
branches:
- main
- spiffui/newui
- keycloak-realm-with-groups
tags: [v*]

jobs:
Expand Down
13 changes: 8 additions & 5 deletions spiffworkflow-backend/keycloak/bin/export_keycloak_realms
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#!/usr/bin/env bash

function error_handler() {
>&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
echo >&2 "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
exit "$2"
}
trap 'error_handler ${LINENO} $?' ERR
set -o errtrace -o errexit -o nounset -o pipefail

script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
script_dir="$(
cd -- "$(dirname "$0")" >/dev/null 2>&1
pwd -P
)"

realms="$*"
if [[ -z "$realms" ]]; then
realms="spiffworkflow-realm"
realms="spiffworkflow-local-realm"
fi

docker_container_path=/tmp/hey
Expand All @@ -20,8 +23,8 @@ docker exec keycloak rm -rf "$docker_container_path"
docker exec keycloak /opt/keycloak/bin/kc.sh export --dir "${docker_container_path}" --users realm_file || echo ''
docker cp "keycloak:${docker_container_path}" "$local_tmp_dir"

for realm in $realms ; do
if ! grep -Eq '\-realm$' <<< "$realm"; then
for realm in $realms; do
if ! grep -Eq '\-realm$' <<<"$realm"; then
realm="${realm}-realm"
fi
cp "${local_tmp_dir}/hey/${realm}.json" "${script_dir}/../realm_exports/"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,17 @@
]
}
},
"groups": [],
"groups": [
{
"id": "a14e6081-ffd4-4925-9364-4916bcf74931",
"name": "group_keycloak",
"path": "/group_keycloak",
"attributes": {},
"realmRoles": [],
"clientRoles": {},
"subGroups": []
}
],
"defaultRole": {
"id": "c9f0ff93-642d-402b-965a-04d70719886b",
"name": "default-roles-spiffworkflow",
Expand All @@ -458,7 +468,11 @@
"otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30,
"otpPolicyCodeReusable": false,
"otpSupportedApplications": ["totpAppFreeOTPName", "totpAppGoogleName"],
"otpSupportedApplications": [
"totpAppMicrosoftAuthenticatorName",
"totpAppFreeOTPName",
"totpAppGoogleName"
],
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": ["ES256"],
"webAuthnPolicyRpId": "",
Expand Down Expand Up @@ -493,7 +507,7 @@
"id": "644ff652-31d1-4349-9340-ce3b5fb76b5c",
"type": "password",
"createdDate": 1676302139645,
"secretData": "{\"value\":\"P6nrEJgmgdL+HbNA9tPkOyHYaLAqLg6cXh27ACgVQiOox4qwNE8Iv1L4ssispV4gsmuHiY+alio/2UMuyMGvEw==\",\"salt\":\"g214ckcAyig59U/3Oqwq4w==\",\"additionalParameters\":{}}",
"secretData": "{\"value\":\"nhHncfQqkY1vhJE8QxjD3hwpznBnZNc5+OxS79OFKJc=\",\"salt\":\"EradsPFeRiQ3oMAzGqfWBw==\",\"additionalParameters\":{}}",
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
}
],
Expand All @@ -504,7 +518,7 @@
"realm-management": ["realm-admin"]
},
"notBefore": 0,
"groups": []
"groups": ["/group_keycloak"]
},
{
"id": "4c436296-8471-4105-b551-80eee96b43bb",
Expand Down Expand Up @@ -651,6 +665,42 @@
"realmRoles": ["default-roles-spiffworkflow"],
"notBefore": 0,
"groups": []
},
{
"id": "d2a86264-e3ca-4a82-99b8-0a6cd714ded4",
"createdTimestamp": 1722019421345,
"username": "service-account-spiffworkflow-backend",
"enabled": true,
"totp": false,
"emailVerified": false,
"serviceAccountClientId": "spiffworkflow-backend",
"credentials": [],
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": ["default-roles-spiffworkflow"],
"clientRoles": {
"spiffworkflow-backend": ["uma_protection"]
},
"notBefore": 0,
"groups": []
},
{
"id": "bae51d14-9d82-468f-9e9d-1cd2cb507f15",
"createdTimestamp": 1722019421396,
"username": "service-account-withauth",
"enabled": true,
"totp": false,
"emailVerified": false,
"serviceAccountClientId": "withAuth",
"credentials": [],
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": ["default-roles-spiffworkflow"],
"clientRoles": {
"withAuth": ["uma_protection"]
},
"notBefore": 0,
"groups": []
}
],
"scopeMappings": [
Expand Down Expand Up @@ -1031,9 +1081,8 @@
"secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q",
"redirectUris": [
"http://localhost:7000/*",
"https://replace-me-with-spiff-backend-host-and-path/*",
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7000/*"
"http://localhost:8000/*",
"https://for-local-dev.spiffworkflow.org/*"
],
"webOrigins": [],
"notBefore": 0,
Expand All @@ -1051,7 +1100,7 @@
"saml.force.post.binding": "false",
"saml.multivalued.roles": "false",
"frontchannel.logout.session.required": "false",
"post.logout.redirect.uris": "https://replace-me-with-spiff-frontend-host-and-path/*##http://localhost:7001/*",
"post.logout.redirect.uris": "https://replace-me-with-spiff-frontend-host-and-path/*##http://localhost:7001/*##http://localhost:8001/*",
"oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.revoke.offline.tokens": "false",
"saml.server.signature.keyinfo.ext": "false",
Expand Down Expand Up @@ -1320,9 +1369,7 @@
"redirectUris": [
"https://api.unused-for-local-dev.spiffworkflow.org/*",
"http://localhost:7001/*",
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7001/*",
"https://api.demo.spiffworkflow.org/*"
"http://localhost:8001/*"
],
"webOrigins": ["*"],
"notBefore": 0,
Expand Down Expand Up @@ -1391,10 +1438,7 @@
"secret": "6o8kIKQznQtejHOdRhWeKorBJclMGcgA",
"redirectUris": [
"https://api.unused-for-local-dev.spiffworkflow.org/*",
"http://localhost:7001/*",
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7001/*",
"https://api.demo.spiffworkflow.org/*"
"http://localhost:8001/*"
],
"webOrigins": [],
"notBefore": 0,
Expand Down Expand Up @@ -1712,6 +1756,20 @@
"jsonType.label": "String"
}
},
{
"id": "75c10b23-3a63-4aa6-99cc-7c8b7645d32f",
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-group-membership-mapper",
"consentRequired": false,
"config": {
"full.path": "true",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"userinfo.token.claim": "true"
}
},
{
"id": "b05e679c-e00e-427e-8e47-0a4fd411c7a6",
"name": "updated at",
Expand Down Expand Up @@ -2071,6 +2129,7 @@
"browserSecurityHeaders": {
"contentSecurityPolicyReportOnly": "",
"xContentTypeOptions": "nosniff",
"referrerPolicy": "no-referrer",
"xRobotsTag": "none",
"xFrameOptions": "SAMEORIGIN",
"contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
Expand Down Expand Up @@ -2106,14 +2165,14 @@
"subComponents": {},
"config": {
"allowed-protocol-mapper-types": [
"saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper",
"saml-user-property-mapper",
"saml-role-list-mapper",
"oidc-address-mapper",
"oidc-full-name-mapper",
"saml-user-attribute-mapper",
"oidc-usermodel-property-mapper",
"saml-role-list-mapper",
"saml-user-property-mapper",
"oidc-usermodel-attribute-mapper"
"oidc-usermodel-property-mapper"
]
}
},
Expand All @@ -2135,14 +2194,14 @@
"subComponents": {},
"config": {
"allowed-protocol-mapper-types": [
"oidc-full-name-mapper",
"saml-user-property-mapper",
"oidc-usermodel-property-mapper",
"saml-role-list-mapper",
"oidc-address-mapper",
"saml-user-property-mapper",
"oidc-full-name-mapper",
"saml-user-attribute-mapper",
"oidc-usermodel-attribute-mapper",
"saml-role-list-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper"
"oidc-usermodel-property-mapper"
]
}
},
Expand Down Expand Up @@ -2281,40 +2340,6 @@
}
]
},
{
"id": "7675760b-666a-4b8c-a9b8-da1e01c207fe",
"alias": "Authentication Options",
"description": "Authentication options.",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "basic-auth",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "basic-auth-otp",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "auth-spnego",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 30,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "34e18ea8-f515-46dc-9dbf-5b79f8154564",
"alias": "Browser - Conditional OTP",
Expand Down Expand Up @@ -2687,32 +2712,6 @@
}
]
},
{
"id": "70ef5a26-e3bb-4ba7-a05a-d205b0a3836c",
"alias": "http challenge",
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "no-cookie-redirect",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "Authentication Options",
"userSetupAllowed": false
}
]
},
{
"id": "89abf09a-bfb4-4dea-b164-ca7c563b4009",
"alias": "registration",
Expand Down Expand Up @@ -2862,9 +2861,9 @@
"config": {}
},
{
"alias": "terms_and_conditions",
"alias": "TERMS_AND_CONDITIONS",
"name": "Terms and Conditions",
"providerId": "terms_and_conditions",
"providerId": "TERMS_AND_CONDITIONS",
"enabled": false,
"defaultAction": false,
"priority": 20,
Expand Down Expand Up @@ -2940,7 +2939,7 @@
"parRequestUriLifespan": "60",
"clientSessionMaxLifespan": "0"
},
"keycloakVersion": "20.0.1",
"keycloakVersion": "22.0.4",
"userManagedAccessAllowed": false,
"clientProfiles": {
"profiles": []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,13 @@ def setup_config(app: Flask) -> None:
if app.config.get("SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS") is None:
app.config["SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS"] = [
{
"additional_valid_client_ids": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_ADDITIONAL_VALID_CLIENT_IDS"),
"client_id": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID"),
"client_secret": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY"),
"identifier": "default",
"internal_uri": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_INTERNAL_URL"),
"label": "Default",
"uri": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL"),
"client_id": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID"),
"client_secret": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY"),
"additional_valid_client_ids": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_ADDITIONAL_VALID_CLIENT_IDS"),
}
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def config_from_env(variable_name: str, *, default: str | bool | int | None = No
SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL = url_config
config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID", default="spiffworkflow-backend")
config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY", default="JXeQExm0JhQPLumgHtIIqf52bDalHz0q")
config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_INTERNAL_URL")

# comma-separated list of client ids that can be successfully validated against.
# useful for api users that will login to a different client on the same realm but from something external to backend.
Expand All @@ -148,6 +149,7 @@ def config_from_env(variable_name: str, *, default: str | bool | int | None = No
{
"identifier": "default",
"label": "Default",
"internal_uri": "http://localhost:7002/realms/spiffworkflow-local",
"uri": "http://localhost:7002/realms/spiffworkflow-local",
"client_id": "spiffworkflow-backend",
"client_secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q",
Expand Down
Loading

0 comments on commit d2c5c27

Please sign in to comment.