nixos/keycloak: Add test
This commit is contained in:
parent
513599a6d7
commit
31fe90d6ef
3 changed files with 143 additions and 1 deletions
|
@ -175,6 +175,7 @@ in
|
|||
kernel-latest = handleTest ./kernel-latest.nix {};
|
||||
kernel-lts = handleTest ./kernel-lts.nix {};
|
||||
kernel-testing = handleTest ./kernel-testing.nix {};
|
||||
keycloak = handleTest ./keycloak.nix {};
|
||||
keymap = handleTest ./keymap.nix {};
|
||||
knot = handleTest ./knot.nix {};
|
||||
krb5 = discoverTests (import ./krb5 {});
|
||||
|
|
139
nixos/tests/keycloak.nix
Normal file
139
nixos/tests/keycloak.nix
Normal file
|
@ -0,0 +1,139 @@
|
|||
# This tests Keycloak: it starts the service, creates a realm with an
|
||||
# OIDC client and a user, and simulates the user logging in to the
|
||||
# client using their Keycloak login.
|
||||
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
frontendUrl = "http://keycloak/auth";
|
||||
initialAdminPassword = "h4IhoJFnt2iQIR9";
|
||||
in
|
||||
{
|
||||
name = "keycloak";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ talyz ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
keycloak = { ... }: {
|
||||
virtualisation.memorySize = 1024;
|
||||
services.keycloak = {
|
||||
enable = true;
|
||||
inherit frontendUrl initialAdminPassword;
|
||||
databasePasswordFile = pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH";
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
xmlstarlet
|
||||
libtidy
|
||||
jq
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
client = {
|
||||
clientId = "test-client";
|
||||
name = "test-client";
|
||||
redirectUris = [ "urn:ietf:wg:oauth:2.0:oob" ];
|
||||
};
|
||||
|
||||
user = {
|
||||
firstName = "Chuck";
|
||||
lastName = "Testa";
|
||||
username = "chuck.testa";
|
||||
email = "chuck.testa@example.com";
|
||||
};
|
||||
|
||||
password = "password1234";
|
||||
|
||||
realm = {
|
||||
enabled = true;
|
||||
realm = "test-realm";
|
||||
clients = [ client ];
|
||||
users = [(
|
||||
user // {
|
||||
enabled = true;
|
||||
credentials = [{
|
||||
type = "password";
|
||||
temporary = false;
|
||||
value = password;
|
||||
}];
|
||||
}
|
||||
)];
|
||||
};
|
||||
|
||||
realmDataJson = pkgs.writeText "realm-data.json" (builtins.toJSON realm);
|
||||
|
||||
jqCheckUserinfo = pkgs.writeText "check-userinfo.jq" ''
|
||||
if {
|
||||
"firstName": .given_name,
|
||||
"lastName": .family_name,
|
||||
"username": .preferred_username,
|
||||
"email": .email
|
||||
} != ${builtins.toJSON user} then
|
||||
error("Wrong user info!")
|
||||
else
|
||||
empty
|
||||
end
|
||||
'';
|
||||
in ''
|
||||
keycloak.start()
|
||||
keycloak.wait_for_unit("keycloak.service")
|
||||
keycloak.wait_until_succeeds("curl -sSf ${frontendUrl}")
|
||||
|
||||
|
||||
### 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"
|
||||
)
|
||||
|
||||
# Publish the realm, including a test OIDC client and user
|
||||
keycloak.succeed(
|
||||
"curl -sSf -H @admin_auth_header -X POST -H 'Content-Type: application/json' -d @${realmDataJson} '${frontendUrl}/admin/realms/'"
|
||||
)
|
||||
|
||||
# Generate and save the client secret. To do this we need
|
||||
# Keycloak's internal id for the client.
|
||||
keycloak.succeed(
|
||||
"curl -sSf -H @admin_auth_header '${frontendUrl}/admin/realms/${realm.realm}/clients?clientId=${client.name}' | jq -r '.[].id' >client_id",
|
||||
"curl -sSf -H @admin_auth_header -X POST '${frontendUrl}/admin/realms/${realm.realm}/clients/'$(<client_id)'/client-secret' | jq -r .value >client_secret",
|
||||
)
|
||||
|
||||
|
||||
### Authentication Testing ###
|
||||
|
||||
# Start the login process by sending an initial request to the
|
||||
# OIDC authentication endpoint, saving the returned page. Tidy
|
||||
# up the HTML (XmlStarlet is picky) and extract the login form
|
||||
# post url.
|
||||
keycloak.succeed(
|
||||
"curl -sSf -c cookie '${frontendUrl}/realms/${realm.realm}/protocol/openid-connect/auth?client_id=${client.name}&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=openid+email&response_type=code&response_mode=query&nonce=qw4o89g3qqm' >login_form",
|
||||
"tidy -q -m login_form || true",
|
||||
"xml sel -T -t -m \"_:html/_:body/_:div/_:div/_:div/_:div/_:div/_:div/_:form[@id='kc-form-login']\" -v @action login_form >form_post_url",
|
||||
)
|
||||
|
||||
# Post the login form and save the response. Once again tidy up
|
||||
# the HTML, then extract the authorization code.
|
||||
keycloak.succeed(
|
||||
"curl -sSf -L -b cookie -d 'username=${user.username}' -d 'password=${password}' -d 'credentialId=' \"$(<form_post_url)\" >auth_code_html",
|
||||
"tidy -q -m auth_code_html || true",
|
||||
"xml sel -T -t -m \"_:html/_:body/_:div/_:div/_:div/_:div/_:div/_:input[@id='code']\" -v @value auth_code_html >auth_code",
|
||||
)
|
||||
|
||||
# Exchange the authorization code for an access token.
|
||||
keycloak.succeed(
|
||||
"curl -sSf -d grant_type=authorization_code -d code=$(<auth_code) -d client_id=${client.name} -d client_secret=$(<client_secret) -d redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob '${frontendUrl}/realms/${realm.realm}/protocol/openid-connect/token' | jq -r '\"Authorization: bearer \" + .access_token' >auth_header"
|
||||
)
|
||||
|
||||
# Use the access token on the OIDC userinfo endpoint and check
|
||||
# that the returned user info matches what we initialized the
|
||||
# realm with.
|
||||
keycloak.succeed(
|
||||
"curl -sSf -H @auth_header '${frontendUrl}/realms/${realm.realm}/protocol/openid-connect/userinfo' | jq -f ${jqCheckUserinfo}"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
{ stdenv, fetchzip, makeWrapper, jre, writeText
|
||||
{ stdenv, fetchzip, makeWrapper, jre, writeText, nixosTests
|
||||
, postgresql_jdbc ? null
|
||||
}:
|
||||
|
||||
|
@ -50,6 +50,8 @@ stdenv.mkDerivation rec {
|
|||
wrapProgram $out/bin/jboss-cli.sh --set JAVA_HOME ${jre}
|
||||
'';
|
||||
|
||||
passthru.tests = nixosTests.keycloak;
|
||||
|
||||
meta = with stdenv.lib; {
|
||||
homepage = "https://www.keycloak.org/";
|
||||
description = "Identity and access management for modern applications and services";
|
||||
|
|
Loading…
Reference in a new issue