[tests] add tests
This commit is contained in:
parent
e2b3a1d944
commit
642f8e9793
10 changed files with 1470 additions and 0 deletions
26
default.nix
Normal file
26
default.nix
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{ pkgs ? import <nixpkgs> {}
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
utils = pkgs.callPackage ./utils.nix {};
|
||||||
|
in
|
||||||
|
with builtins;
|
||||||
|
with pkgs.lib.attrsets;
|
||||||
|
with pkgs.lib.lists;
|
||||||
|
with pkgs.lib.strings;
|
||||||
|
rec {
|
||||||
|
tests = pkgs.callPackage ./tests { inherit utils; };
|
||||||
|
|
||||||
|
runtests =
|
||||||
|
let
|
||||||
|
onlytests = filterAttrs (name: value: name != "override" && name != "overrideDerivation") tests;
|
||||||
|
failingtests = filterAttrs (name: value: length value > 0) onlytests;
|
||||||
|
formatFailure = failure: toString failure; # TODO: make this more pretty
|
||||||
|
formattedFailureGroups = mapAttrsToList (name: failures: "${name}:\n${concatMapStringsSep "\n" formatFailure failures}") failingtests;
|
||||||
|
in
|
||||||
|
if length formattedFailureGroups == 0 then
|
||||||
|
"no failing test"
|
||||||
|
else
|
||||||
|
concatStringsSep "\n" formattedFailureGroups;
|
||||||
|
|
||||||
|
disnixtests = pkgs.callPackage ./tests/disnix/keycloak.nix {};
|
||||||
|
}
|
12
tests/default.nix
Normal file
12
tests/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# to run all tests:
|
||||||
|
# nix-instantiate --eval --strict . -A tests
|
||||||
|
|
||||||
|
{ pkgs
|
||||||
|
, utils
|
||||||
|
}:
|
||||||
|
|
||||||
|
{
|
||||||
|
haproxy = pkgs.callPackage ./haproxy.nix { inherit utils; };
|
||||||
|
keycloak = pkgs.callPackage ./keycloak.nix {};
|
||||||
|
keycloak-cli-config = pkgs.callPackage ./keycloak-cli-config.nix {};
|
||||||
|
}
|
93
tests/disnix/keycloak.nix
Normal file
93
tests/disnix/keycloak.nix
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
{ nixpkgs ? <nixpkgs>
|
||||||
|
, system ? builtins.currentSystem
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {inherit system;};
|
||||||
|
|
||||||
|
disnixos = import "${pkgs.disnixos}/share/disnixos/testing.nix" {
|
||||||
|
inherit nixpkgs system;
|
||||||
|
};
|
||||||
|
|
||||||
|
version = "1.0";
|
||||||
|
in
|
||||||
|
|
||||||
|
rec {
|
||||||
|
tarball = disnixos.sourceTarball {
|
||||||
|
name = "testproject-zip";
|
||||||
|
inherit version;
|
||||||
|
src = ./.;
|
||||||
|
officialRelease = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
manifest =
|
||||||
|
disnixos.buildManifest {
|
||||||
|
name = "test-project-manifest";
|
||||||
|
version = builtins.readFile ./version;
|
||||||
|
inherit tarball;
|
||||||
|
servicesFile = "keycloak/services.nix";
|
||||||
|
networkFile = "keycloak/network.nix";
|
||||||
|
distributionFile = "keycloak/distribution.nix";
|
||||||
|
};
|
||||||
|
|
||||||
|
tests =
|
||||||
|
disnixos.disnixTest {
|
||||||
|
name = "test-project-tests";
|
||||||
|
inherit tarball manifest;
|
||||||
|
networkFile = "keycloak/network.nix";
|
||||||
|
dysnomiaStateDir = /var/state/dysnomia;
|
||||||
|
testScript =
|
||||||
|
''
|
||||||
|
# Wait until the front-end application is deployed
|
||||||
|
$test1->waitForFile("/var/tomcat/webapps/testapp");
|
||||||
|
|
||||||
|
# Wait a little longer and capture the output of the entry page
|
||||||
|
my $result = $test1->mustSucceed("sleep 10; curl --fail http://test2:8080/testapp");
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
# let
|
||||||
|
# utils = import ../../utils.nix {
|
||||||
|
# inherit pkgs;
|
||||||
|
# inherit (pkgs) stdenv lib;
|
||||||
|
# };
|
||||||
|
# keycloak = import ../../pkgs/keycloak/unit.nix {
|
||||||
|
# inherit pkgs utils;
|
||||||
|
# inherit (pkgs) stdenv lib;
|
||||||
|
# };
|
||||||
|
# in
|
||||||
|
# makeTest {
|
||||||
|
# nodes = {
|
||||||
|
# machine = {config, pkgs, ...}:
|
||||||
|
# {
|
||||||
|
# virtualisation.memorySize = 1024;
|
||||||
|
# virtualisation.diskSize = 4096;
|
||||||
|
|
||||||
|
# environment.systemPackages = [ dysnomia pkgs.curl ];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# testScript = ''
|
||||||
|
# def check_keycloak_activated():
|
||||||
|
# machine.succeed("sleep 5")
|
||||||
|
# machine.succeed("curl --fail http://keycloak.test.tiserbox.com")
|
||||||
|
|
||||||
|
# def check_keycloak_deactivated():
|
||||||
|
# machine.succeed("sleep 5")
|
||||||
|
# machine.fail("curl --fail http://keycloak.test.tiserbox.com")
|
||||||
|
|
||||||
|
# start_all()
|
||||||
|
|
||||||
|
# # Test the keycloak module. Start keycloak and see if we can query the endpoint.
|
||||||
|
# machine.succeed(
|
||||||
|
# "dysnomia --type docker-container --operation activate --component ${keycloak} --environment"
|
||||||
|
# )
|
||||||
|
# check_keycloak_activated()
|
||||||
|
|
||||||
|
# # Deactivate keycloak. Check if it is not running anymore
|
||||||
|
# machine.succeed(
|
||||||
|
# "dysnomia --type docker-container --operation deactivate --component ${keycloak} --environment"
|
||||||
|
# )
|
||||||
|
# check_keycloak_deactivated()
|
||||||
|
# '';
|
||||||
|
# }
|
7
tests/disnix/keycloak/distribution.nix
Normal file
7
tests/disnix/keycloak/distribution.nix
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{ infrastructure }:
|
||||||
|
|
||||||
|
with infrastructure;
|
||||||
|
{
|
||||||
|
KeycloakPostgresDB = [ test1 ];
|
||||||
|
KeycloakService = [ test1 ];
|
||||||
|
}
|
75
tests/disnix/keycloak/network.nix
Normal file
75
tests/disnix/keycloak/network.nix
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
rec {
|
||||||
|
test1 = { system
|
||||||
|
, pkgs
|
||||||
|
, lib
|
||||||
|
, ... }:
|
||||||
|
let
|
||||||
|
domain = "local";
|
||||||
|
|
||||||
|
utils = pkgs.lib.callPackageWith pkgs ../../../utils.nix { };
|
||||||
|
|
||||||
|
customPkgs = import ../../../pkgs/all-packages.nix {
|
||||||
|
inherit system pkgs utils;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
users.groups = {
|
||||||
|
keycloak = {
|
||||||
|
name = "keycloak";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
users.users = {
|
||||||
|
keycloak = {
|
||||||
|
name = "keycloak";
|
||||||
|
group = "keycloak";
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
deployment.keys = {
|
||||||
|
keycloakinitialadmin.text = ''
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD="${builtins.extraBuiltins.pass "keycloak.${domain}/admin"}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
openssh = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
disnix = {
|
||||||
|
enable = true;
|
||||||
|
# useWebServiceInterface = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
postgresql = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.postgresql_14;
|
||||||
|
|
||||||
|
port = 5432;
|
||||||
|
enableTCPIP = true;
|
||||||
|
authentication = pkgs.lib.mkOverride 10 ''
|
||||||
|
local all all trust
|
||||||
|
host all all 127.0.0.1/32 trust
|
||||||
|
host all all ::1/128 trust
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dysnomia = {
|
||||||
|
enable = true;
|
||||||
|
enableLegacyModules = false;
|
||||||
|
extraContainerProperties = {
|
||||||
|
system = {
|
||||||
|
inherit domain;
|
||||||
|
};
|
||||||
|
postgresql-database = {
|
||||||
|
service_name = "postgresql.service";
|
||||||
|
port = builtins.toString services.postgresql.port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ services.postgresql.port ];
|
||||||
|
};
|
||||||
|
}
|
45
tests/disnix/keycloak/services.nix
Normal file
45
tests/disnix/keycloak/services.nix
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{ system, pkgs, distribution, invDistribution }:
|
||||||
|
|
||||||
|
let
|
||||||
|
utils = pkgs.lib.callPackageWith pkgs ../../../utils.nix { };
|
||||||
|
|
||||||
|
customPkgs = import ../../../pkgs/all-packages.nix {
|
||||||
|
inherit system pkgs utils;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
KeycloakPostgresDB = customPkgs.mkPostgresDB {
|
||||||
|
name = "KeycloakPostgresDB";
|
||||||
|
database = "keycloak";
|
||||||
|
username = "keycloak";
|
||||||
|
# TODO: use passwordFile
|
||||||
|
password = "keycloak";
|
||||||
|
};
|
||||||
|
|
||||||
|
KeycloakService = customPkgs.mkKeycloakService {
|
||||||
|
name = "KeycloakService";
|
||||||
|
|
||||||
|
# Get these from infrastructure.nix
|
||||||
|
user = "keycloak";
|
||||||
|
group = "keycloak";
|
||||||
|
|
||||||
|
postgresServiceName = (utils.getTarget "KeycloakPostgresDB").containers.postgresql-database.service_name;
|
||||||
|
initialAdminUsername = "admin";
|
||||||
|
|
||||||
|
keys = {
|
||||||
|
dbPassword = "keycloakdbpassword";
|
||||||
|
initialAdminPassword = "keycloakinitialadmin";
|
||||||
|
};
|
||||||
|
|
||||||
|
logLevel = "INFO";
|
||||||
|
hostname = "keycloak.${getDomain "KeycloakService"}";
|
||||||
|
|
||||||
|
dbType = "postgres";
|
||||||
|
dbDatabase = KeycloakPostgresDB.database;
|
||||||
|
dbUsername = KeycloakPostgresDB.username;
|
||||||
|
dbHost = {KeycloakPostgresDB}: KeycloakPostgresDB.target.properties.hostname;
|
||||||
|
dbPort = (getTarget "KeycloakPostgresDB").containers.postgresql-database.port;
|
||||||
|
|
||||||
|
inherit KeycloakPostgresDB;
|
||||||
|
};
|
||||||
|
}
|
549
tests/haproxy.nix
Normal file
549
tests/haproxy.nix
Normal file
|
@ -0,0 +1,549 @@
|
||||||
|
# to run these tests:
|
||||||
|
# nix-instantiate --eval --strict . -A tests.haproxy
|
||||||
|
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, pkgs
|
||||||
|
, utils
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
configcreator = pkgs.callPackage ./../haproxy/configcreator.nix { inherit utils; };
|
||||||
|
mksiteconfig = pkgs.callPackage ./../haproxy/siteconfig.nix {};
|
||||||
|
|
||||||
|
diff = testResult:
|
||||||
|
with builtins;
|
||||||
|
with lib.strings;
|
||||||
|
if isString testResult.expected && isString testResult.result then
|
||||||
|
let
|
||||||
|
p = commonPrefixLength testResult.expected testResult.result;
|
||||||
|
s = commonSuffixLength testResult.expected testResult.result;
|
||||||
|
expectedSuffixLen = stringLength testResult.expected - s - p;
|
||||||
|
resultSuffixLen = stringLength testResult.result - s - p;
|
||||||
|
expectedDiff = substring p expectedSuffixLen testResult.expected;
|
||||||
|
resultDiff = substring p resultSuffixLen testResult.result;
|
||||||
|
omitted = len: if len == 0 then "" else "[... ${toString len} omitted]";
|
||||||
|
in
|
||||||
|
{inherit (testResult) name;
|
||||||
|
commonPrefix = substring 0 p testResult.expected;
|
||||||
|
commonSuffix = substring (stringLength testResult.expected - s) s testResult.expected;
|
||||||
|
expected = "${omitted p}${expectedDiff}${omitted s}";
|
||||||
|
result = "${omitted p}${resultDiff}${omitted s}";
|
||||||
|
allExpected = testResult.expected;
|
||||||
|
allResult = testResult.result;
|
||||||
|
}
|
||||||
|
else testResult;
|
||||||
|
|
||||||
|
runTests = x: map diff (lib.runTests x);
|
||||||
|
in
|
||||||
|
|
||||||
|
with lib.attrsets;
|
||||||
|
runTests {
|
||||||
|
testDiffSame = {
|
||||||
|
expr = "abdef";
|
||||||
|
expected = "abdef";
|
||||||
|
};
|
||||||
|
testUpdateByPath1 = {
|
||||||
|
expr = configcreator.updateByPath ["a"] (x: x+1) {
|
||||||
|
a = 1;
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
a = 2;
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
testUpdateByPath2 = {
|
||||||
|
expr = configcreator.updateByPath ["a" "a"] (x: x+1) {
|
||||||
|
a = {
|
||||||
|
a = 1;
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
a = {
|
||||||
|
a = 2;
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
testUpdateByPath3 = {
|
||||||
|
expr = configcreator.updateByPath ["a" "a" "a"] (x: x+1) {
|
||||||
|
a = {
|
||||||
|
a = {
|
||||||
|
a = 1;
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
a = {
|
||||||
|
a = {
|
||||||
|
a = 2;
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
b = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testRecursiveMerge1 = {
|
||||||
|
expr = configcreator.recursiveMerge [
|
||||||
|
{a = 1;}
|
||||||
|
{b = 2;}
|
||||||
|
];
|
||||||
|
expected = {
|
||||||
|
a = 1;
|
||||||
|
b = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testRecursiveMerge2 = {
|
||||||
|
expr = configcreator.recursiveMerge [
|
||||||
|
{a = {a = 1; b = 2;};}
|
||||||
|
{a = {a = 2;};}
|
||||||
|
];
|
||||||
|
expected = {
|
||||||
|
a = {a = 2; b = 2;};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
tesFlattenArgs1 = {
|
||||||
|
expr = configcreator.flattenAttrs {
|
||||||
|
a = 1;
|
||||||
|
b = 2;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
a = 1;
|
||||||
|
b = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
tesFlattenArgs2 = {
|
||||||
|
expr = configcreator.flattenAttrs {
|
||||||
|
a = {
|
||||||
|
a = 1;
|
||||||
|
b = {
|
||||||
|
c = 3;
|
||||||
|
d = 4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = 2;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
"a.a" = 1;
|
||||||
|
"a.b.c" = 3;
|
||||||
|
"a.b.d" = 4;
|
||||||
|
b = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testHaproxyConfigDefaultRender = {
|
||||||
|
expr = configcreator.render (configcreator.default {
|
||||||
|
user = "me";
|
||||||
|
group = "mygroup";
|
||||||
|
certPath = "/cert/path";
|
||||||
|
plugins = {
|
||||||
|
zone = {
|
||||||
|
luapaths = "lib";
|
||||||
|
source = pkgs.writeText "one.lua" "a binary";
|
||||||
|
};
|
||||||
|
two = {
|
||||||
|
load = "right/two.lua";
|
||||||
|
luapaths = ".";
|
||||||
|
cpaths = "right";
|
||||||
|
source = pkgs.writeText "two.lua" "a binary";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
globalEnvs = {
|
||||||
|
ABC = "hello";
|
||||||
|
};
|
||||||
|
stats = null;
|
||||||
|
debug = false;
|
||||||
|
});
|
||||||
|
expected = ''
|
||||||
|
global
|
||||||
|
group mygroup
|
||||||
|
log /dev/log local0 info
|
||||||
|
maxconn 20000
|
||||||
|
lua-prepend-path /nix/store/ybcka9g095hp8s1hnm2ncfh1hp56v9yq-haproxyplugins/two/?.lua path
|
||||||
|
lua-prepend-path /nix/store/ybcka9g095hp8s1hnm2ncfh1hp56v9yq-haproxyplugins/two/right/?.so cpath
|
||||||
|
lua-prepend-path /nix/store/ybcka9g095hp8s1hnm2ncfh1hp56v9yq-haproxyplugins/zone/lib/?.lua path
|
||||||
|
lua-load /nix/store/ybcka9g095hp8s1hnm2ncfh1hp56v9yq-haproxyplugins/two/right/two.lua
|
||||||
|
setenv ABC hello
|
||||||
|
tune.ssl.default-dh-param 2048
|
||||||
|
user me
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
option httplog
|
||||||
|
timeout client 15s
|
||||||
|
timeout connect 10s
|
||||||
|
timeout queue 100s
|
||||||
|
timeout server 30s
|
||||||
|
|
||||||
|
frontend http-to-https
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
|
||||||
|
frontend https
|
||||||
|
bind *:443 ssl crt /cert/path
|
||||||
|
http-request add-header X-Forwarded-Proto https
|
||||||
|
http-request set-header X-Forwarded-Port %[dst_port]
|
||||||
|
http-request set-header X-Forwarded-For %[src]
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
|
||||||
|
mode http
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
testHaproxyConfigDefaultRenderWithStatsAndDebug = {
|
||||||
|
expr = configcreator.render (configcreator.default {
|
||||||
|
user = "me";
|
||||||
|
group = "mygroup";
|
||||||
|
certPath = "/cert/path";
|
||||||
|
stats = {
|
||||||
|
port = 8405;
|
||||||
|
uri = "/stats";
|
||||||
|
refresh = "10s";
|
||||||
|
prometheusUri = "/prom/etheus";
|
||||||
|
hide-version = true;
|
||||||
|
};
|
||||||
|
debug = true;
|
||||||
|
});
|
||||||
|
expected = ''
|
||||||
|
global
|
||||||
|
group mygroup
|
||||||
|
log /dev/log local0 info
|
||||||
|
maxconn 20000
|
||||||
|
tune.ssl.default-dh-param 2048
|
||||||
|
user me
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
option httplog
|
||||||
|
timeout client 15s
|
||||||
|
timeout connect 10s
|
||||||
|
timeout queue 100s
|
||||||
|
timeout server 30s
|
||||||
|
|
||||||
|
frontend http-to-https
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
|
||||||
|
frontend https
|
||||||
|
bind *:443 ssl crt /cert/path
|
||||||
|
http-request add-header X-Forwarded-Proto https
|
||||||
|
http-request set-header X-Forwarded-Port %[dst_port]
|
||||||
|
http-request set-header X-Forwarded-For %[src]
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
|
||||||
|
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %sslv %sslc %[ssl_fc_cipherlist_str]"
|
||||||
|
mode http
|
||||||
|
|
||||||
|
frontend stats
|
||||||
|
bind localhost:8405
|
||||||
|
http-request use-service prometheus-exporter if { path /prom/etheus }
|
||||||
|
mode http
|
||||||
|
stats enable
|
||||||
|
stats hide-version
|
||||||
|
stats refresh 10s
|
||||||
|
stats uri /stats
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
testRenderHaproxyConfigWithSite = {
|
||||||
|
expr = configcreator.render (configcreator.default {
|
||||||
|
user = "me";
|
||||||
|
group = "mygroup";
|
||||||
|
certPath = "/cert/path";
|
||||||
|
stats = null;
|
||||||
|
debug = false;
|
||||||
|
sites = {
|
||||||
|
siteName = {
|
||||||
|
frontend = {
|
||||||
|
capture = [
|
||||||
|
"request header origin len 128"
|
||||||
|
];
|
||||||
|
acl = {
|
||||||
|
acl_siteName = "hdr_beg(host) siteName.";
|
||||||
|
acl_siteName_path = "path_beg /siteName";
|
||||||
|
};
|
||||||
|
http-response = {
|
||||||
|
add-header = [
|
||||||
|
"Access-Control-Allow-Origin1 $[capture]"
|
||||||
|
"Access-Control-Allow-Origin2 $[capture]"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
use_backend = "if acl_siteName OR acl_siteName_path";
|
||||||
|
};
|
||||||
|
backend = {
|
||||||
|
servers = [
|
||||||
|
{
|
||||||
|
name = "serviceName1";
|
||||||
|
address = "serviceSocket";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
options = [
|
||||||
|
"cookie JSESSIONID prefix"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expected = ''
|
||||||
|
global
|
||||||
|
group mygroup
|
||||||
|
log /dev/log local0 info
|
||||||
|
maxconn 20000
|
||||||
|
tune.ssl.default-dh-param 2048
|
||||||
|
user me
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
option httplog
|
||||||
|
timeout client 15s
|
||||||
|
timeout connect 10s
|
||||||
|
timeout queue 100s
|
||||||
|
timeout server 30s
|
||||||
|
|
||||||
|
frontend http-to-https
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
|
||||||
|
frontend https
|
||||||
|
acl acl_siteName hdr_beg(host) siteName.
|
||||||
|
acl acl_siteName_path path_beg /siteName
|
||||||
|
bind *:443 ssl crt /cert/path
|
||||||
|
capture request header origin len 128
|
||||||
|
http-request add-header X-Forwarded-Proto https
|
||||||
|
http-request set-header X-Forwarded-Port %[dst_port]
|
||||||
|
http-request set-header X-Forwarded-For %[src]
|
||||||
|
http-response add-header Access-Control-Allow-Origin1 $[capture]
|
||||||
|
http-response add-header Access-Control-Allow-Origin2 $[capture]
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
|
||||||
|
mode http
|
||||||
|
use_backend siteName if acl_siteName OR acl_siteName_path
|
||||||
|
|
||||||
|
backend siteName
|
||||||
|
cookie JSESSIONID prefix
|
||||||
|
mode http
|
||||||
|
option forwardfor
|
||||||
|
server serviceName1 serviceSocket
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
testRenderHaproxyConfigWith2Sites = {
|
||||||
|
expr = configcreator.render (configcreator.default {
|
||||||
|
user = "me";
|
||||||
|
group = "mygroup";
|
||||||
|
certPath = "/cert/path";
|
||||||
|
stats = null;
|
||||||
|
debug = false;
|
||||||
|
sites = {
|
||||||
|
siteName = {
|
||||||
|
frontend = {
|
||||||
|
capture = [
|
||||||
|
"request header origin len 128"
|
||||||
|
];
|
||||||
|
acl = {
|
||||||
|
acl_siteName = "hdr_beg(host) siteName.";
|
||||||
|
acl_siteName_path = "path_beg /siteName";
|
||||||
|
};
|
||||||
|
http-response = {
|
||||||
|
add-header = [
|
||||||
|
"Access-Control-Allow-Origin1 $[capture]"
|
||||||
|
"Access-Control-Allow-Origin2 $[capture]"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
use_backend = "if acl_siteName OR acl_siteName_path";
|
||||||
|
};
|
||||||
|
backend = {
|
||||||
|
servers = [
|
||||||
|
{
|
||||||
|
name = "serviceName1";
|
||||||
|
address = "serviceSocket";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
options = [
|
||||||
|
"cookie JSESSIONID prefix"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
siteName2 = {
|
||||||
|
frontend = {
|
||||||
|
capture = [
|
||||||
|
"request header origin len 128"
|
||||||
|
];
|
||||||
|
acl = {
|
||||||
|
acl_siteName2 = "hdr_beg(host) siteName2.";
|
||||||
|
acl_siteName2_path = "path_beg /siteName2";
|
||||||
|
};
|
||||||
|
http-response = {
|
||||||
|
add-header = [
|
||||||
|
"Access-Control-Allow-Origin3 $[capture]"
|
||||||
|
"Access-Control-Allow-Origin4 $[capture]"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
use_backend = "if acl_siteName2 OR acl_siteName2_path";
|
||||||
|
};
|
||||||
|
backend = {
|
||||||
|
servers = [
|
||||||
|
{
|
||||||
|
name = "serviceName2";
|
||||||
|
address = "serviceSocket";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
options = [
|
||||||
|
"cookie JSESSIONID prefix"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expected = ''
|
||||||
|
global
|
||||||
|
group mygroup
|
||||||
|
log /dev/log local0 info
|
||||||
|
maxconn 20000
|
||||||
|
tune.ssl.default-dh-param 2048
|
||||||
|
user me
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
option httplog
|
||||||
|
timeout client 15s
|
||||||
|
timeout connect 10s
|
||||||
|
timeout queue 100s
|
||||||
|
timeout server 30s
|
||||||
|
|
||||||
|
frontend http-to-https
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
|
||||||
|
frontend https
|
||||||
|
acl acl_siteName hdr_beg(host) siteName.
|
||||||
|
acl acl_siteName2 hdr_beg(host) siteName2.
|
||||||
|
acl acl_siteName2_path path_beg /siteName2
|
||||||
|
acl acl_siteName_path path_beg /siteName
|
||||||
|
bind *:443 ssl crt /cert/path
|
||||||
|
capture request header origin len 128
|
||||||
|
capture request header origin len 128
|
||||||
|
http-request add-header X-Forwarded-Proto https
|
||||||
|
http-request set-header X-Forwarded-Port %[dst_port]
|
||||||
|
http-request set-header X-Forwarded-For %[src]
|
||||||
|
http-response add-header Access-Control-Allow-Origin1 $[capture]
|
||||||
|
http-response add-header Access-Control-Allow-Origin2 $[capture]
|
||||||
|
http-response add-header Access-Control-Allow-Origin3 $[capture]
|
||||||
|
http-response add-header Access-Control-Allow-Origin4 $[capture]
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
|
||||||
|
mode http
|
||||||
|
use_backend siteName if acl_siteName OR acl_siteName_path
|
||||||
|
use_backend siteName2 if acl_siteName2 OR acl_siteName2_path
|
||||||
|
|
||||||
|
backend siteName
|
||||||
|
cookie JSESSIONID prefix
|
||||||
|
mode http
|
||||||
|
option forwardfor
|
||||||
|
server serviceName1 serviceSocket
|
||||||
|
|
||||||
|
backend siteName2
|
||||||
|
cookie JSESSIONID prefix
|
||||||
|
mode http
|
||||||
|
option forwardfor
|
||||||
|
server serviceName2 serviceSocket
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
testRenderHaproxyConfigWithSiteDebugHeaders = {
|
||||||
|
expr = configcreator.render (configcreator.default {
|
||||||
|
user = "me";
|
||||||
|
group = "mygroup";
|
||||||
|
certPath = "/cert/path";
|
||||||
|
stats = null;
|
||||||
|
debug = false;
|
||||||
|
sites = {
|
||||||
|
siteName = {
|
||||||
|
frontend = {
|
||||||
|
capture = [
|
||||||
|
"request header origin len 128"
|
||||||
|
];
|
||||||
|
acl = {
|
||||||
|
acl_siteName = "hdr_beg(host) siteName.";
|
||||||
|
acl_siteName_path = "path_beg /siteName";
|
||||||
|
};
|
||||||
|
http-response = {
|
||||||
|
add-header = [
|
||||||
|
"Access-Control-Allow-Origin1 $[capture]"
|
||||||
|
"Access-Control-Allow-Origin2 $[capture]"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
use_backend = "if acl_siteName OR acl_siteName_path";
|
||||||
|
};
|
||||||
|
backend = {
|
||||||
|
servers = [
|
||||||
|
{
|
||||||
|
name = "serviceName1";
|
||||||
|
address = "serviceSocket";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
options = [
|
||||||
|
"cookie JSESSIONID prefix"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
debugHeaders = "acl_siteName";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expected = ''
|
||||||
|
global
|
||||||
|
group mygroup
|
||||||
|
log /dev/log local0 info
|
||||||
|
maxconn 20000
|
||||||
|
tune.ssl.default-dh-param 2048
|
||||||
|
user me
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
option httplog
|
||||||
|
timeout client 15s
|
||||||
|
timeout connect 10s
|
||||||
|
timeout queue 100s
|
||||||
|
timeout server 30s
|
||||||
|
|
||||||
|
frontend http-to-https
|
||||||
|
bind *:80
|
||||||
|
mode http
|
||||||
|
redirect scheme https code 301 if !{ ssl_fc }
|
||||||
|
|
||||||
|
frontend https
|
||||||
|
acl acl_siteName hdr_beg(host) siteName.
|
||||||
|
acl acl_siteName_path path_beg /siteName
|
||||||
|
bind *:443 ssl crt /cert/path
|
||||||
|
capture request header origin len 128
|
||||||
|
http-request add-header X-Forwarded-Proto https
|
||||||
|
http-request capture req.hdrs len 512 if acl_siteName
|
||||||
|
http-request set-header X-Forwarded-Port %[dst_port]
|
||||||
|
http-request set-header X-Forwarded-For %[src]
|
||||||
|
http-response add-header Access-Control-Allow-Origin1 $[capture]
|
||||||
|
http-response add-header Access-Control-Allow-Origin2 $[capture]
|
||||||
|
http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;"
|
||||||
|
log-format "%ci:%cp [%tr] %ft [[%hr]] %hs %{+Q}r"
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
use_backend siteName if acl_siteName OR acl_siteName_path
|
||||||
|
|
||||||
|
backend siteName
|
||||||
|
cookie JSESSIONID prefix
|
||||||
|
mode http
|
||||||
|
option forwardfor
|
||||||
|
server serviceName1 serviceSocket
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
343
tests/keycloak-cli-config.nix
Normal file
343
tests/keycloak-cli-config.nix
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
# to run these tests:
|
||||||
|
# nix-instantiate --eval --strict . -A tests.keycloak-cli-config
|
||||||
|
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, pkgs
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
configcreator = pkgs.callPackage ./../keycloak-cli-config/configcreator.nix { };
|
||||||
|
|
||||||
|
default_config = {
|
||||||
|
realm = "myrealm";
|
||||||
|
domain = "mydomain.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
keep_fields = fields:
|
||||||
|
lib.filterAttrs (n: v: lib.any (n_: n_ == n) fields);
|
||||||
|
in
|
||||||
|
|
||||||
|
lib.runTests {
|
||||||
|
testDefault = {
|
||||||
|
expr = configcreator default_config;
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
id = "myrealm";
|
||||||
|
realm = "myrealm";
|
||||||
|
enabled = true;
|
||||||
|
clients = [];
|
||||||
|
roles = {
|
||||||
|
realm = [];
|
||||||
|
client = {};
|
||||||
|
};
|
||||||
|
groups = [];
|
||||||
|
users = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testUsers = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
users = {
|
||||||
|
me = {
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})).users;
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
username = "me";
|
||||||
|
enabled = true;
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
emailVerified = true;
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testUsersWithGroups = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
users = {
|
||||||
|
me = {
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
groups = [ "MyGroup" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})).users;
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
username = "me";
|
||||||
|
enabled = true;
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
emailVerified = true;
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
groups = [ "MyGroup" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testUsersWithRoles = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
users = {
|
||||||
|
me = {
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
roles = [ "MyRole" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})).users;
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
username = "me";
|
||||||
|
enabled = true;
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
emailVerified = true;
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
realmRoles = [ "MyRole" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testUsersWithInitialPassword = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
users = {
|
||||||
|
me = {
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
initialPassword = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})).users;
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
username = "me";
|
||||||
|
enabled = true;
|
||||||
|
email = "me@mydomain.com";
|
||||||
|
emailVerified = true;
|
||||||
|
firstName = "me";
|
||||||
|
lastName = "stillme";
|
||||||
|
credentials = [
|
||||||
|
{
|
||||||
|
type = "password";
|
||||||
|
userLabel = "initial";
|
||||||
|
value = "$(keycloak.users.me.password)";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testGroups = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
groups = [ "MyGroup" ];
|
||||||
|
})).groups;
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
name = "MyGroup";
|
||||||
|
path = "/MyGroup";
|
||||||
|
attributes = {};
|
||||||
|
realmRoles = [];
|
||||||
|
clientRoles = {};
|
||||||
|
subGroups = [];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testRealmRoles = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
roles = {
|
||||||
|
A = [ "B" ];
|
||||||
|
B = [ ];
|
||||||
|
};
|
||||||
|
})).roles;
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
client = {};
|
||||||
|
realm = [
|
||||||
|
{
|
||||||
|
name = "A";
|
||||||
|
composite = true;
|
||||||
|
composites = {
|
||||||
|
realm = [ "B" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "B";
|
||||||
|
composite = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testClientRoles = {
|
||||||
|
expr = (configcreator (default_config // {
|
||||||
|
clients = {
|
||||||
|
clientA = {
|
||||||
|
roles = [ "cA" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})).roles;
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
client = {
|
||||||
|
clientA = [
|
||||||
|
{
|
||||||
|
name = "cA";
|
||||||
|
clientRole = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
realm = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testClient = {
|
||||||
|
expr = map (keep_fields [
|
||||||
|
"clientId"
|
||||||
|
"rootUrl"
|
||||||
|
"redirectUris"
|
||||||
|
"webOrigins"
|
||||||
|
"authorizationSettings"
|
||||||
|
]) (configcreator (default_config // {
|
||||||
|
clients = {
|
||||||
|
clientA = {};
|
||||||
|
};
|
||||||
|
})).clients;
|
||||||
|
expected = [
|
||||||
|
{
|
||||||
|
clientId = "clientA";
|
||||||
|
rootUrl = "https://clientA.mydomain.com";
|
||||||
|
redirectUris = ["https://clientA.mydomain.com/oauth2/callback"];
|
||||||
|
webOrigins = ["https://clientA.mydomain.com"];
|
||||||
|
authorizationSettings = {
|
||||||
|
policyEnforcementMode = "ENFORCING";
|
||||||
|
resources = [];
|
||||||
|
policies = [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testClientAuthorization = with builtins; {
|
||||||
|
expr = (head (configcreator (default_config // {
|
||||||
|
clients = {
|
||||||
|
clientA = {
|
||||||
|
resourcesUris = {
|
||||||
|
adminPath = ["/admin/*"];
|
||||||
|
userPath = ["/*"];
|
||||||
|
};
|
||||||
|
access = {
|
||||||
|
admin = {
|
||||||
|
roles = [ "admin" ];
|
||||||
|
resources = [ "adminPath" ];
|
||||||
|
};
|
||||||
|
user = {
|
||||||
|
roles = [ "user" ];
|
||||||
|
resources = [ "userPath" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})).clients).authorizationSettings;
|
||||||
|
expected = {
|
||||||
|
policyEnforcementMode = "ENFORCING";
|
||||||
|
resources = [
|
||||||
|
{
|
||||||
|
name = "adminPath";
|
||||||
|
type = "urn:clientA:resources:adminPath";
|
||||||
|
ownerManagedAccess = false;
|
||||||
|
uris = ["/admin/*"];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "userPath";
|
||||||
|
type = "urn:clientA:resources:userPath";
|
||||||
|
ownerManagedAccess = false;
|
||||||
|
uris = ["/*"];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
policies = [
|
||||||
|
{
|
||||||
|
name = "admin has access";
|
||||||
|
type = "role";
|
||||||
|
logic = "POSITIVE";
|
||||||
|
decisionStrategy = "UNANIMOUS";
|
||||||
|
config = {
|
||||||
|
roles = ''[{"id":"admin","required":true}]'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "user has access";
|
||||||
|
type = "role";
|
||||||
|
logic = "POSITIVE";
|
||||||
|
decisionStrategy = "UNANIMOUS";
|
||||||
|
config = {
|
||||||
|
roles = ''[{"id":"user","required":true}]'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "admin has access to adminPath";
|
||||||
|
type = "resource";
|
||||||
|
logic = "POSITIVE";
|
||||||
|
decisionStrategy = "UNANIMOUS";
|
||||||
|
config = {
|
||||||
|
resources = ''["adminPath"]'';
|
||||||
|
applyPolicies = ''["admin has access"]'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "user has access to userPath";
|
||||||
|
type = "resource";
|
||||||
|
logic = "POSITIVE";
|
||||||
|
decisionStrategy = "UNANIMOUS";
|
||||||
|
config = {
|
||||||
|
resources = ''["userPath"]'';
|
||||||
|
applyPolicies = ''["user has access"]'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testClientAudience =
|
||||||
|
let
|
||||||
|
audienceProtocolMapper = config:
|
||||||
|
with builtins;
|
||||||
|
let
|
||||||
|
protocolMappers = (head config.clients).protocolMappers;
|
||||||
|
protocolMapperByName = name: protocolMappers: head (filter (x: x.name == name) protocolMappers);
|
||||||
|
in
|
||||||
|
protocolMapperByName "Audience" protocolMappers;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
expr = audienceProtocolMapper (configcreator (default_config // {
|
||||||
|
clients = {
|
||||||
|
clientA = {};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
expected = {
|
||||||
|
name = "Audience";
|
||||||
|
protocol = "openid-connect";
|
||||||
|
protocolMapper = "oidc-audience-mapper";
|
||||||
|
config = {
|
||||||
|
"included.client.audience" = "clientA";
|
||||||
|
"id.token.claim" = "false";
|
||||||
|
"access.token.claim" = "true";
|
||||||
|
"included.custom.audience" = "clientA";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
232
tests/keycloak.nix
Normal file
232
tests/keycloak.nix
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
# to run these tests:
|
||||||
|
# nix-instantiate --eval --strict . -A tests.keycloak
|
||||||
|
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, pkgs
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
configcreator = pkgs.callPackage ./../keycloak-cli-config/configcreator.nix {};
|
||||||
|
in
|
||||||
|
|
||||||
|
with lib.attrsets;
|
||||||
|
lib.runTests {
|
||||||
|
testConfigEmpty = {
|
||||||
|
expr = configcreator {
|
||||||
|
realm = "myrealm";
|
||||||
|
domain = "domain.com";
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
id = "myrealm";
|
||||||
|
realm = "myrealm";
|
||||||
|
enabled = true;
|
||||||
|
clients = [];
|
||||||
|
groups = [];
|
||||||
|
roles = {
|
||||||
|
client = {};
|
||||||
|
realm = [];
|
||||||
|
};
|
||||||
|
users = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testConfigRole = {
|
||||||
|
expr = configcreator {
|
||||||
|
realm = "myrealm";
|
||||||
|
domain = "domain.com";
|
||||||
|
roles = {
|
||||||
|
user = [];
|
||||||
|
admin = ["user"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
id = "myrealm";
|
||||||
|
realm = "myrealm";
|
||||||
|
enabled = true;
|
||||||
|
clients = [];
|
||||||
|
groups = [];
|
||||||
|
roles = {
|
||||||
|
realm = [
|
||||||
|
{
|
||||||
|
name = "admin";
|
||||||
|
composite = true;
|
||||||
|
composites = {
|
||||||
|
realm = ["user"];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "user";
|
||||||
|
composite = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
client = {};
|
||||||
|
};
|
||||||
|
users = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testConfigClient = {
|
||||||
|
expr =
|
||||||
|
let
|
||||||
|
c = configcreator {
|
||||||
|
realm = "myrealm";
|
||||||
|
domain = "domain.com";
|
||||||
|
clients = {
|
||||||
|
myclient = {};
|
||||||
|
myclient2 = {
|
||||||
|
roles = ["uma"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
updateManyAttrsByPath [
|
||||||
|
{
|
||||||
|
path = [ "clients" ];
|
||||||
|
# We don't care about the value of the protocolMappers
|
||||||
|
# field because its value is hardcoded.
|
||||||
|
update = clients: map (filterAttrs (n: v: n != "protocolMappers")) clients;
|
||||||
|
}
|
||||||
|
] c;
|
||||||
|
expected = {
|
||||||
|
id = "myrealm";
|
||||||
|
realm = "myrealm";
|
||||||
|
enabled = true;
|
||||||
|
clients = [
|
||||||
|
{
|
||||||
|
clientId = "myclient";
|
||||||
|
rootUrl = "https://myclient.domain.com";
|
||||||
|
clientAuthenticatorType = "client-secret";
|
||||||
|
redirectUris = [
|
||||||
|
"https://myclient.domain.com/oauth2/callback"
|
||||||
|
];
|
||||||
|
webOrigins = [
|
||||||
|
"https://myclient.domain.com"
|
||||||
|
];
|
||||||
|
authorizationServicesEnabled = true;
|
||||||
|
serviceAccountsEnabled = true;
|
||||||
|
protocol = "openid-connect";
|
||||||
|
publicClient = false;
|
||||||
|
authorizationSettings = {
|
||||||
|
policyEnforcementMode = "ENFORCING";
|
||||||
|
resources = [];
|
||||||
|
policies = [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
clientId = "myclient2";
|
||||||
|
rootUrl = "https://myclient2.domain.com";
|
||||||
|
clientAuthenticatorType = "client-secret";
|
||||||
|
redirectUris = [
|
||||||
|
"https://myclient2.domain.com/oauth2/callback"
|
||||||
|
];
|
||||||
|
webOrigins = [
|
||||||
|
"https://myclient2.domain.com"
|
||||||
|
];
|
||||||
|
authorizationServicesEnabled = true;
|
||||||
|
serviceAccountsEnabled = true;
|
||||||
|
protocol = "openid-connect";
|
||||||
|
publicClient = false;
|
||||||
|
authorizationSettings = {
|
||||||
|
policyEnforcementMode = "ENFORCING";
|
||||||
|
resources = [];
|
||||||
|
policies = [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
groups = [];
|
||||||
|
roles = {
|
||||||
|
client = {
|
||||||
|
myclient = [];
|
||||||
|
myclient2 = [
|
||||||
|
{
|
||||||
|
name = "uma";
|
||||||
|
clientRole = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
realm = [];
|
||||||
|
};
|
||||||
|
users = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testConfigUser = {
|
||||||
|
expr = configcreator {
|
||||||
|
realm = "myrealm";
|
||||||
|
domain = "domain.com";
|
||||||
|
users = {
|
||||||
|
me = {
|
||||||
|
email = "me@me.com";
|
||||||
|
firstName = null;
|
||||||
|
lastName = "Me";
|
||||||
|
realmRoles = [ "role" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
id = "myrealm";
|
||||||
|
realm = "myrealm";
|
||||||
|
enabled = true;
|
||||||
|
clients = [];
|
||||||
|
groups = [];
|
||||||
|
roles = {
|
||||||
|
client = {};
|
||||||
|
realm = [];
|
||||||
|
};
|
||||||
|
users = [
|
||||||
|
{
|
||||||
|
enabled = true;
|
||||||
|
username = "me";
|
||||||
|
email = "me@me.com";
|
||||||
|
emailVerified = true;
|
||||||
|
firstName = null;
|
||||||
|
lastName = "Me";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testConfigUserInitialPassword = {
|
||||||
|
expr = configcreator {
|
||||||
|
realm = "myrealm";
|
||||||
|
domain = "domain.com";
|
||||||
|
users = {
|
||||||
|
me = {
|
||||||
|
email = "me@me.com";
|
||||||
|
firstName = null;
|
||||||
|
lastName = "Me";
|
||||||
|
initialPassword = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
id = "myrealm";
|
||||||
|
realm = "myrealm";
|
||||||
|
enabled = true;
|
||||||
|
clients = [];
|
||||||
|
groups = [];
|
||||||
|
roles = {
|
||||||
|
client = {};
|
||||||
|
realm = [];
|
||||||
|
};
|
||||||
|
users = [
|
||||||
|
{
|
||||||
|
enabled = true;
|
||||||
|
username = "me";
|
||||||
|
email = "me@me.com";
|
||||||
|
emailVerified = true;
|
||||||
|
firstName = null;
|
||||||
|
lastName = "Me";
|
||||||
|
credentials = [
|
||||||
|
{
|
||||||
|
type = "password";
|
||||||
|
userLabel = "initial";
|
||||||
|
value = "$(keycloak.users.me.password)";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
88
utils.nix
Normal file
88
utils.nix
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
{ stdenv
|
||||||
|
, pkgs
|
||||||
|
, lib
|
||||||
|
}:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
with lib.lists;
|
||||||
|
with lib.attrsets;
|
||||||
|
rec {
|
||||||
|
tmpFilesFromDirectories = user: group: d:
|
||||||
|
let
|
||||||
|
wrapTmpfiles = dir: mode: "d '${dir}' ${mode} ${user} ${group} - -";
|
||||||
|
in
|
||||||
|
mapAttrsToList wrapTmpfiles d;
|
||||||
|
|
||||||
|
systemd = {
|
||||||
|
mkService = {name, content, timer ? null}: stdenv.mkDerivation {
|
||||||
|
inherit name;
|
||||||
|
|
||||||
|
src = pkgs.writeTextDir "${name}.service" content;
|
||||||
|
timerSrc = pkgs.writeTextDir "${name}.timer" timer;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/etc/systemd/system
|
||||||
|
cp $src/*.service $out/etc/systemd/system
|
||||||
|
'' + (if timer == null then "" else ''
|
||||||
|
cp $timerSrc/*.timer $out/etc/systemd/system
|
||||||
|
'');
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
mkConfigFile = {dir, name, content}: stdenv.mkDerivation rec {
|
||||||
|
inherit name;
|
||||||
|
|
||||||
|
src = pkgs.writeTextDir name content;
|
||||||
|
|
||||||
|
buildCommand = ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp ${src}/${name} $out/${name}
|
||||||
|
|
||||||
|
echo "${dir}" > $out/.dysnomia-targetdir
|
||||||
|
|
||||||
|
cat > $out/.dysnomia-fileset <<FILESET
|
||||||
|
symlink $out/${name}
|
||||||
|
target .
|
||||||
|
FILESET
|
||||||
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
dnsmasqConfig = domain: subdomains:
|
||||||
|
''
|
||||||
|
${concatMapStringsSep "\n" (x: "address=/${x}.${domain}/127.0.0.1") subdomains}
|
||||||
|
domain=${domain}
|
||||||
|
'';
|
||||||
|
|
||||||
|
keyEnvironmentFile = path: "EnvironmentFile=/run/keys/${path}";
|
||||||
|
keyEnvironmentFiles = names: concatMapStrings (path: "${keyEnvironmentFile path}\n") (attrValues names);
|
||||||
|
keyServiceDependencies = names: concatMapStringsSep " " (path: "${path}-key.service") (attrValues names);
|
||||||
|
|
||||||
|
recursiveMerge = attrList:
|
||||||
|
let f = attrPath:
|
||||||
|
zipAttrsWith (n: values:
|
||||||
|
if all isList values then
|
||||||
|
concatLists values
|
||||||
|
else if all isAttrs values then
|
||||||
|
f (attrPath ++ [n]) values
|
||||||
|
else
|
||||||
|
last values
|
||||||
|
);
|
||||||
|
in f [] attrList;
|
||||||
|
|
||||||
|
getTarget = distribution: name: builtins.elemAt (builtins.getAttr name distribution) 0;
|
||||||
|
|
||||||
|
getDomain = distribution: name: (getTarget distribution name).containers.system.domain;
|
||||||
|
|
||||||
|
unitDepends = verb: dependsOn:
|
||||||
|
let
|
||||||
|
withSystemdUnitFile = filter (hasAttr "systemdUnitFile") (attrValues dependsOn);
|
||||||
|
|
||||||
|
systemdUnitFiles = map (x: x.systemdUnitFile) withSystemdUnitFile;
|
||||||
|
in
|
||||||
|
if length systemdUnitFiles == 0 then
|
||||||
|
""
|
||||||
|
else
|
||||||
|
"${verb}=${concatStringsSep " " systemdUnitFiles}";
|
||||||
|
}
|
Loading…
Reference in a new issue