Loading nixos/modules/services/web-apps/keycloak.nix +25 −2 Original line number Diff line number Diff line Loading @@ -482,6 +482,10 @@ in assertion = (cfg.database.useSSL && cfg.database.type == "postgresql") -> (cfg.database.caCert != null); message = "A CA certificate must be specified (in 'services.keycloak.database.caCert') when PostgreSQL is used with SSL"; } { assertion = createLocalPostgreSQL -> config.services.postgresql.settings.standard_conforming_strings or true; message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably"; } ]; environment.systemPackages = [ keycloakBuild ]; Loading Loading @@ -544,7 +548,13 @@ in create_role="$(mktemp)" trap 'rm -f "$create_role"' EXIT # Read the password from the credentials directory and # escape any single quotes by adding additional single # quotes after them, following the rules laid out here: # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" db_password="''${db_password//\'/\'\'}" echo "CREATE ROLE keycloak WITH LOGIN PASSWORD '$db_password' CREATEDB" > "$create_role" psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || psql -tA --file="$create_role" psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || psql -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"' Loading @@ -566,8 +576,16 @@ in script = '' set -o errexit -o pipefail -o nounset -o errtrace shopt -s inherit_errexit # Read the password from the credentials directory and # escape any single quotes by adding additional single # quotes after them, following the rules laid out here: # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" ( echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';" db_password="''${db_password//\'/\'\'}" ( echo "SET sql_mode = 'NO_BACKSLASH_ESCAPES';" echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';" echo "CREATE DATABASE IF NOT EXISTS keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;" echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';" ) | mysql -N Loading Loading @@ -632,12 +650,17 @@ in ${secretReplacements} # Escape any backslashes in the db parameters, since # they're otherwise unexpectedly read as escape # sequences. sed -i '/db-/ s|\\|\\\\|g' /run/keycloak/conf/keycloak.conf '' + optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' mkdir -p /run/keycloak/ssl cp $CREDENTIALS_DIRECTORY/ssl_{cert,key} /run/keycloak/ssl/ '' + '' export KEYCLOAK_ADMIN=admin export KEYCLOAK_ADMIN_PASSWORD=${cfg.initialAdminPassword} export KEYCLOAK_ADMIN_PASSWORD=${escapeShellArg cfg.initialAdminPassword} kc.sh start --optimized ''; }; Loading nixos/tests/keycloak.nix +10 −7 Original line number Diff line number Diff line Loading @@ -5,10 +5,13 @@ let certs = import ./common/acme/server/snakeoil-certs.nix; frontendUrl = "https://${certs.domain}"; initialAdminPassword = "h4IhoJFnt2iQIR9"; keycloakTest = import ./make-test-python.nix ( { pkgs, databaseType, ... }: let initialAdminPassword = "h4Iho\"JFn't2>iQIR9"; adminPasswordFile = pkgs.writeText "admin-password" "${initialAdminPassword}"; in { name = "keycloak"; meta = with pkgs.lib.maintainers; { Loading Loading @@ -37,7 +40,7 @@ let type = databaseType; username = "bogus"; name = "also bogus"; passwordFile = "${pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH"}"; passwordFile = "${pkgs.writeText "dbPassword" ''wzf6\"vO"Cb\nP>p#6;c&o?eu=q'THE'''H''''E''}"; }; plugins = with config.services.keycloak.package.plugins; [ keycloak-discord Loading Loading @@ -111,7 +114,7 @@ let keycloak.succeed(""" curl -sSf -d 'client_id=admin-cli' \ -d 'username=admin' \ -d 'password=${initialAdminPassword}' \ -d "password=$(<${adminPasswordFile})" \ -d 'grant_type=password' \ '${frontendUrl}/realms/master/protocol/openid-connect/token' \ | jq -r '"Authorization: bearer " + .access_token' >admin_auth_header Loading @@ -119,10 +122,10 @@ let # Register the metrics SPI keycloak.succeed( "${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt", "KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password '${initialAdminPassword}'", "KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'", "curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'" """${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt""", """KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password "$(<${adminPasswordFile})" """, """KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'""", """curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'""" ) # Publish the realm, including a test OIDC client and user Loading Loading
nixos/modules/services/web-apps/keycloak.nix +25 −2 Original line number Diff line number Diff line Loading @@ -482,6 +482,10 @@ in assertion = (cfg.database.useSSL && cfg.database.type == "postgresql") -> (cfg.database.caCert != null); message = "A CA certificate must be specified (in 'services.keycloak.database.caCert') when PostgreSQL is used with SSL"; } { assertion = createLocalPostgreSQL -> config.services.postgresql.settings.standard_conforming_strings or true; message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably"; } ]; environment.systemPackages = [ keycloakBuild ]; Loading Loading @@ -544,7 +548,13 @@ in create_role="$(mktemp)" trap 'rm -f "$create_role"' EXIT # Read the password from the credentials directory and # escape any single quotes by adding additional single # quotes after them, following the rules laid out here: # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" db_password="''${db_password//\'/\'\'}" echo "CREATE ROLE keycloak WITH LOGIN PASSWORD '$db_password' CREATEDB" > "$create_role" psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || psql -tA --file="$create_role" psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || psql -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"' Loading @@ -566,8 +576,16 @@ in script = '' set -o errexit -o pipefail -o nounset -o errtrace shopt -s inherit_errexit # Read the password from the credentials directory and # escape any single quotes by adding additional single # quotes after them, following the rules laid out here: # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" ( echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';" db_password="''${db_password//\'/\'\'}" ( echo "SET sql_mode = 'NO_BACKSLASH_ESCAPES';" echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';" echo "CREATE DATABASE IF NOT EXISTS keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;" echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';" ) | mysql -N Loading Loading @@ -632,12 +650,17 @@ in ${secretReplacements} # Escape any backslashes in the db parameters, since # they're otherwise unexpectedly read as escape # sequences. sed -i '/db-/ s|\\|\\\\|g' /run/keycloak/conf/keycloak.conf '' + optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' mkdir -p /run/keycloak/ssl cp $CREDENTIALS_DIRECTORY/ssl_{cert,key} /run/keycloak/ssl/ '' + '' export KEYCLOAK_ADMIN=admin export KEYCLOAK_ADMIN_PASSWORD=${cfg.initialAdminPassword} export KEYCLOAK_ADMIN_PASSWORD=${escapeShellArg cfg.initialAdminPassword} kc.sh start --optimized ''; }; Loading
nixos/tests/keycloak.nix +10 −7 Original line number Diff line number Diff line Loading @@ -5,10 +5,13 @@ let certs = import ./common/acme/server/snakeoil-certs.nix; frontendUrl = "https://${certs.domain}"; initialAdminPassword = "h4IhoJFnt2iQIR9"; keycloakTest = import ./make-test-python.nix ( { pkgs, databaseType, ... }: let initialAdminPassword = "h4Iho\"JFn't2>iQIR9"; adminPasswordFile = pkgs.writeText "admin-password" "${initialAdminPassword}"; in { name = "keycloak"; meta = with pkgs.lib.maintainers; { Loading Loading @@ -37,7 +40,7 @@ let type = databaseType; username = "bogus"; name = "also bogus"; passwordFile = "${pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH"}"; passwordFile = "${pkgs.writeText "dbPassword" ''wzf6\"vO"Cb\nP>p#6;c&o?eu=q'THE'''H''''E''}"; }; plugins = with config.services.keycloak.package.plugins; [ keycloak-discord Loading Loading @@ -111,7 +114,7 @@ let keycloak.succeed(""" curl -sSf -d 'client_id=admin-cli' \ -d 'username=admin' \ -d 'password=${initialAdminPassword}' \ -d "password=$(<${adminPasswordFile})" \ -d 'grant_type=password' \ '${frontendUrl}/realms/master/protocol/openid-connect/token' \ | jq -r '"Authorization: bearer " + .access_token' >admin_auth_header Loading @@ -119,10 +122,10 @@ let # Register the metrics SPI keycloak.succeed( "${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt", "KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password '${initialAdminPassword}'", "KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'", "curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'" """${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt""", """KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password "$(<${adminPasswordFile})" """, """KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'""", """curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'""" ) # Publish the realm, including a test OIDC client and user Loading