diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix index 22c16be76139..c4a2127663a9 100644 --- a/nixos/modules/services/web-apps/keycloak.nix +++ b/nixos/modules/services/web-apps/keycloak.nix @@ -129,6 +129,14 @@ in ''; }; + plugins = lib.mkOption { + type = lib.types.listOf lib.types.path; + default = []; + description = '' + Keycloak plugin jar, ear files or derivations with them + ''; + }; + database = { type = mkOption { type = enum [ "mysql" "postgresql" ]; @@ -787,6 +795,14 @@ in umask u=rwx,g=,o= + install_plugin() { + if [ -d "$1" ]; then + find "$1" -type f \( -iname \*.ear -o -iname \*.jar \) -exec install -m 0500 -o keycloak -g keycloak "{}" "/run/keycloak/deployments/" \; + else + install -m 0500 -o keycloak -g keycloak "$1" "/run/keycloak/deployments/" + fi + } + install -m 0600 ${cfg.package}/standalone/configuration/*.properties /run/keycloak/configuration install -T -m 0600 ${keycloakConfig} /run/keycloak/configuration/standalone.xml @@ -794,7 +810,9 @@ in export JAVA_OPTS=-Djboss.server.config.user.dir=/run/keycloak/configuration add-user-keycloak.sh -u admin -p '${cfg.initialAdminPassword}' - '' + optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' + '' + + lib.optionalString (cfg.plugins != []) (lib.concatStringsSep "\n" (map (pl: "install_plugin ${lib.escapeShellArg pl}") cfg.plugins)) + "\n" + + optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' pushd /run/keycloak/ssl/ cat "$CREDENTIALS_DIRECTORY/ssl_cert" <(echo) \ "$CREDENTIALS_DIRECTORY/ssl_key" <(echo) \ diff --git a/nixos/tests/keycloak.nix b/nixos/tests/keycloak.nix index 6367ed808e06..fce8df2b7e3a 100644 --- a/nixos/tests/keycloak.nix +++ b/nixos/tests/keycloak.nix @@ -16,8 +16,7 @@ let }; nodes = { - keycloak = { ... }: { - + keycloak = { config, ... }: { security.pki.certificateFiles = [ certs.ca.cert ]; @@ -36,6 +35,10 @@ let username = "bogus"; passwordFile = pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH"; }; + plugins = with config.services.keycloak.package.plugins; [ + keycloak-discord + keycloak-metrics-spi + ]; }; environment.systemPackages = with pkgs; [ @@ -102,8 +105,21 @@ let ### Realm Setup ### # Get an admin interface access token + keycloak.succeed(""" + curl -sSf -d 'client_id=admin-cli' \ + -d 'username=admin' \ + -d 'password=${initialAdminPassword}' \ + -d 'grant_type=password' \ + '${frontendUrl}/realms/master/protocol/openid-connect/token' \ + | jq -r '"Authorization: bearer " + .access_token' >admin_auth_header + """) + + # Register the metrics SPI keycloak.succeed( - "curl -sSf -d 'client_id=admin-cli' -d 'username=admin' -d 'password=${initialAdminPassword}' -d 'grant_type=password' '${frontendUrl}/realms/master/protocol/openid-connect/token' | jq -r '\"Authorization: bearer \" + .access_token' >admin_auth_header" + "${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' ${pkgs.keycloak}/bin/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' ${pkgs.keycloak}/bin/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 diff --git a/pkgs/applications/misc/dbeaver/default.nix b/pkgs/applications/misc/dbeaver/default.nix index 56485e69d421..d713afc96a3f 100644 --- a/pkgs/applications/misc/dbeaver/default.nix +++ b/pkgs/applications/misc/dbeaver/default.nix @@ -16,9 +16,10 @@ , maven , webkitgtk , glib-networking +, javaPackages }: -stdenv.mkDerivation rec { +javaPackages.mavenfod rec { pname = "dbeaver"; version = "22.0.1"; # When updating also update fetchedMavenDeps.sha256 @@ -29,6 +30,10 @@ stdenv.mkDerivation rec { sha256 = "sha256-IG5YWwq3WVzQBvAslQ9Z2Ou6ADzf4n9NkQCtH4Jgkac="; }; + + mvnSha256 = "7Sm1hAoi5xc4MLONOD8ySLLkpao0qmlMRRva/8zR210="; + mvnParameters = "-P desktop,all-platforms"; + fetchedMavenDeps = stdenv.mkDerivation { name = "dbeaver-${version}-maven-deps"; inherit src; @@ -37,7 +42,7 @@ stdenv.mkDerivation rec { maven ]; - buildPhase = "mvn package -Dmaven.repo.local=$out/.m2 -P desktop,all-platforms"; + buildPhase = "mvn package -Dmaven.repo.local=$out/.m2 ${mvnParameters}"; # keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with lastModified timestamps inside installPhase = '' @@ -88,14 +93,6 @@ stdenv.mkDerivation rec { }) ]; - buildPhase = '' - runHook preBuild - - mvn package --offline -Dmaven.repo.local=$(cp -dpR ${fetchedMavenDeps}/.m2 ./ && chmod +w -R .m2 && pwd)/.m2 -P desktop,all-platforms - - runHook postBuild - ''; - installPhase = let productTargetPath = "product/community/target/products/org.jkiss.dbeaver.core.product"; diff --git a/pkgs/development/java-modules/maven-fod.nix b/pkgs/development/java-modules/maven-fod.nix new file mode 100644 index 000000000000..24ce572af574 --- /dev/null +++ b/pkgs/development/java-modules/maven-fod.nix @@ -0,0 +1,56 @@ +{ lib +, stdenv +, maven +}: + +{ src +, patches ? [] +, pname +, version +, mvnSha256 ? "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" +, mvnHash ? "sha256-${mvnSha256}" +, mvnFetchExtraArgs ? {} +, mvnParameters ? "" +, ... +} @args: + +# originally extracted from dbeaver +# created to allow using maven packages in the same style as rust + +stdenv.mkDerivation (rec { + fetchedMavenDeps = stdenv.mkDerivation ({ + name = "${pname}-${version}-maven-deps"; + inherit src; + + buildInputs = [ + maven + ]; + + buildPhase = '' + mvn package -Dmaven.repo.local=$out/.m2 ${mvnParameters} + ''; + + # keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with lastModified timestamps inside + installPhase = '' + find $out -type f \ + -name \*.lastUpdated -or \ + -name resolver-status.properties -or \ + -name _remote.repositories \ + -delete + ''; + + # don't do any fixup + dontFixup = true; + outputHashMode = "recursive"; + outputHash = mvnHash; + } // mvnFetchExtraArgs); + + buildPhase = '' + runHook preBuild + + mvnDeps=$(cp -dpR ${fetchedMavenDeps}/.m2 ./ && chmod +w -R .m2 && pwd) + mvn package --offline "-Dmaven.repo.local=$mvnDeps/.m2" -P desktop,all-platforms + + runHook postBuild + ''; +} // args) diff --git a/pkgs/servers/keycloak/all-plugins.nix b/pkgs/servers/keycloak/all-plugins.nix new file mode 100644 index 000000000000..4dbd24872631 --- /dev/null +++ b/pkgs/servers/keycloak/all-plugins.nix @@ -0,0 +1,7 @@ +{ callPackage }: + +{ + scim-for-keycloak = callPackage ./scim-for-keycloak {}; + keycloak-discord = callPackage ./keycloak-discord {}; + keycloak-metrics-spi = callPackage ./keycloak-metrics-spi {}; +} diff --git a/pkgs/servers/keycloak/default.nix b/pkgs/servers/keycloak/default.nix index 19268de42ff1..d9797de6d174 100644 --- a/pkgs/servers/keycloak/default.nix +++ b/pkgs/servers/keycloak/default.nix @@ -1,5 +1,6 @@ { stdenv, lib, fetchzip, makeWrapper, jre, writeText, nixosTests , postgresql_jdbc ? null, mysql_jdbc ? null +, callPackage }: let @@ -57,7 +58,10 @@ stdenv.mkDerivation rec { wrapProgram $out/bin/kcreg.sh --prefix PATH : ${jre}/bin ''; - passthru.tests = nixosTests.keycloak; + passthru = { + tests = nixosTests.keycloak; + plugins = callPackage ./all-plugins.nix {}; + }; meta = with lib; { homepage = "https://www.keycloak.org/"; diff --git a/pkgs/servers/keycloak/keycloak-discord/default.nix b/pkgs/servers/keycloak/keycloak-discord/default.nix new file mode 100644 index 000000000000..047bc67fbc56 --- /dev/null +++ b/pkgs/servers/keycloak/keycloak-discord/default.nix @@ -0,0 +1,29 @@ +{ stdenv +, lib +, fetchurl +}: + +stdenv.mkDerivation rec { + pname = "keycloak-discord"; + version = "0.3.1"; + + src = fetchurl { + url = "https://github.com/wadahiro/keycloak-discord/releases/download/v${version}/keycloak-discord-ear-${version}.ear"; + sha256 = "0fswhbnxc80dpfqf5y6j29dxk3vcnm4kki6qdk22qliasvpw5n9c"; + }; + + dontUnpack = true; + dontBuild = true; + + installPhase = '' + mkdir -p "$out" + install "$src" "$out/${pname}-ear-${version}.ear" + ''; + + meta = with lib; { + homepage = "https://github.com/wadahiro/keycloak-discord"; + description = "Keycloak Social Login extension for Discord"; + license = licenses.apsl20; + maintainers = with maintainers; [ mkg20001 ]; + }; +} diff --git a/pkgs/servers/keycloak/keycloak-metrics-spi/default.nix b/pkgs/servers/keycloak/keycloak-metrics-spi/default.nix new file mode 100644 index 000000000000..b5e23d0fe22d --- /dev/null +++ b/pkgs/servers/keycloak/keycloak-metrics-spi/default.nix @@ -0,0 +1,26 @@ +{ stdenv, lib, fetchurl }: + +stdenv.mkDerivation rec { + pname = "keycloak-metrics-spi"; + version = "2.5.3"; + + src = fetchurl { + url = "https://github.com/aerogear/keycloak-metrics-spi/releases/download/${version}/keycloak-metrics-spi-${version}.jar"; + sha256 = "15lsy8wjw6nlfdfhllc45z9l5474p0lsghrwzzsssvd68bw54gwv"; + }; + + dontUnpack = true; + dontBuild = true; + + installPhase = '' + mkdir -p $out + install "$src" "$out" + ''; + + meta = with lib; { + homepage = "https://github.com/aerogear/keycloak-metrics-spi"; + description = "Keycloak Service Provider that adds a metrics endpoint"; + license = licenses.apsl20; + maintainers = with maintainers; [ benley ]; + }; +} diff --git a/pkgs/servers/keycloak/scim-for-keycloak/default.nix b/pkgs/servers/keycloak/scim-for-keycloak/default.nix new file mode 100644 index 000000000000..1ef06061326e --- /dev/null +++ b/pkgs/servers/keycloak/scim-for-keycloak/default.nix @@ -0,0 +1,36 @@ +{ lib +, stdenv +, fetchFromGitHub +, maven +, javaPackages +}: + +javaPackages.mavenfod rec { + pname = "scim-for-keycloak"; + version = "kc-15-b2"; # When updating also update mvnHash + + src = fetchFromGitHub { + owner = "Captain-P-Goldfish"; + repo = "scim-for-keycloak"; + rev = version; + sha256 = "K34c7xISjEETI3jFkRLdZ0C8pZHTWtPtrrIzwC76Tv0="; + }; + + mvnHash = "sha256-kDYhXTEOAWH/dcRJalKtbwBpoxcD1aX9eqcRKs6ewbE="; + + nativeBuildInputs = [ + maven + ]; + + installPhase = '' + EAR=$(find -iname "*.ear") + install -D "$EAR" "$out/$(basename $EAR)" + ''; + + meta = with lib; { + homepage = "https://github.com/Captain-P-Goldfish/scim-for-keycloak"; + description = "A third party module that extends Keycloak with SCIM functionality"; + license = licenses.bsd3; + maintainers = with maintainers; [ mkg20001 ]; + }; +} diff --git a/pkgs/top-level/java-packages.nix b/pkgs/top-level/java-packages.nix index c8d9e85fbd77..160f51cf43c5 100644 --- a/pkgs/top-level/java-packages.nix +++ b/pkgs/top-level/java-packages.nix @@ -10,8 +10,10 @@ let openjfx15 = callPackage ../development/compilers/openjdk/openjfx/15.nix { }; openjfx17 = callPackage ../development/compilers/openjdk/openjfx/17.nix { }; + mavenfod = callPackage ../development/java-modules/maven-fod.nix { }; + in { - inherit mavenbuild fetchMaven openjfx11 openjfx15 openjfx17; + inherit mavenbuild mavenfod fetchMaven openjfx11 openjfx15 openjfx17; compiler = let