Skip to content

Commit

Permalink
Add keycloak and LDAP for SSO
Browse files Browse the repository at this point in the history
  • Loading branch information
e1mo committed Aug 13, 2023
1 parent f809aaf commit 3151375
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 3 deletions.
1 change: 1 addition & 0 deletions hosts/goldberg/configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
../../services/vaultwarden.nix
../../services/dokuwiki.nix
../../services/freescout.nix
../../services/keycloak
];

system.stateVersion = "23.05";
Expand Down
30 changes: 30 additions & 0 deletions packages/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,34 @@ final: prev:
installPhase = "mkdir -p $out; cp -R * $out/";
};
};

keycloak-registration-captcha = final.maven.buildMavenPackage rec {
pname = "keycloak-registration-captcha";
version = "1.1.0";
src = final.fetchFromGitHub {
owner = "chaos-jetzt";
repo = pname;
rev = "v${version}";
hash = "sha256-133cMOSHtDj1eTS01AuiNQa7aI0tNSCt1rg1mgCEinw=";
};

nativeBuildInputs = [ final.maven ];

mvnHash = "sha256-GTFDjQT7g1sMfIbH/wkxBS0yJDctW5l3QFsv2aggPN0=";

installPhase = ''
runHook preInstall
install -Dm444 -t "$out" target/registration-captcha.jar
runHook postInstall
'';
};

cj-keycloak-theme = final.fetchFromGitHub rec {
pname = "cj-keycloak-theme";
version = "2020-12-19-${builtins.substring 0 6 rev}";
owner = "chaos-jetzt";
repo = "cj-keycloak-theme";
rev = "3075080f828782cfae076c8f4f7866112f544d94";
hash = "sha256-uGUFPE1o0RaKxXh+Vv+OUxCSnyzARo9v2ucWHchW/wg=";
};
}
8 changes: 6 additions & 2 deletions secrets/goldberg/secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ dokuwiki:
keycloak_key: ENC[AES256_GCM,data:/6+NWA==,iv:61M+OdGx3lCR3uFWmArpYUm9Q4L+pv656V8g257YMTw=,tag:fOESdHA6+bpMMDRbWRFn+A==,type:str]
vaultwarden:
env: ENC[AES256_GCM,data:mDqHHAjisl0din/q67+zH7NMKLXld9qC0Si6ZREhRStXr6HEFD/QwaGLN86AvUI7sHNf9l4nrgKOht7uXNJrkjuidGsFEEJWkuUOjBRnrtipNKV2YK7giPQXEhH7wTdGeaqxqi4sk90Oq/FoKi2vPkFyNWGOQ5vOXkKKXjjHnbyKIQkIRWya2Dy6IN0CXU8UK0OiQXY3kgEFOyJoqt4sx/HOScHNKkaLb8U+0rpfzxSVyP3oY4o/DFkE51bnd/CNKg3ZK4Ynp/5m7Rs=,iv:aWpDXSp6Ds7cfdw/vfM3I5wcHz0MytnhpIIWEa24LBE=,tag:5YZKo4ZCT57gji8iyBMAiQ==,type:str]
keycloak:
db_password: ENC[AES256_GCM,data:fRSCENb0II+obekeD82JtjSgKfMsfQHPn33jft7xCHqkEpAkBk5TZ30rYGJOQ+09hdKx4NTFS6iYMG1jEDYDLw==,iv:RhsPKrjj+IaRRUK5NELKPTS2vkO7GnTWRMySpzJlzvs=,tag:YOO9cx4nMJwXeiNHoAPsEw==,type:str]
ldap:
admin_password: ENC[AES256_GCM,data:Xj8DiRYGf6Kgk6nnhKfblbQ3u2hcJgl+m+piJpw1ivyJ8224laX9HZHZqYWtczOZi7oy2ddF5XcLVEh0rLa/4w==,iv:dJqusylgVsn0elF3yRuV+6bDB3KiKdxnVf0UL7DE+YQ=,tag:+7oP5sQliwSOF2OE4dO5BA==,type:str]
sops:
kms: []
gcp_kms: []
Expand All @@ -24,8 +28,8 @@ sops:
QjBmYlNYWlFoWHd0ZFJkWE0xMkpvZzQKJwKap35S2pWGNOtBHe931dRqAQAczbWv
/BUEtl900F8YLQCB1/myV0Dk5X9XDlww1yrzw/La3gXANY93Ndu3MA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2022-12-24T23:32:14Z"
mac: ENC[AES256_GCM,data:H6fvAvgQCx/iXcLnId7KW5wQ/xMpW/IELg9saYOC6UBMngXNMAoneEgTtmo89Dbwvc2e1qo5fzkk7XacBTx6SNOq27gwPUyfsNKD/V+VPpJtAV+PH47CoR83pnS0uPbiyCAIJvp+bXBI9LNMBb6VrrqR7NqKva2BG528n6b3LUQ=,iv:9KyBPOKu4swk6IZCNt/xI9DKqeuwyG7z1aEXIXDxVvg=,tag:hIVSBQd/85C0+sEiCKGQ/w==,type:str]
lastmodified: "2023-08-13T13:49:48Z"
mac: ENC[AES256_GCM,data:VBV0sLgEHqG4Ff3OW9Zxtm8424xm074tzz3sEupJL/JYYzJBTQLqjBTzNik1OvlYF6Xmp32yK8Jkp6F6Q6VH3azcwXqVK8qX0VBqlIw/dJLLp+jK5+bgkJR2bd+QlaHbmVGB6ZZbuOc1J2FhOJHHia+0JwSfjcEUtnV9/VvEwsg=,iv:OIlgDGT6Vsh4JqoCDh8kgXOyjVRva1wbx8LBaxGVDb0=,tag:Gu9QC+Ni2D4W3DZ4S+lhfQ==,type:str]
pgp:
- created_at: "2023-07-23T14:01:56Z"
enc: |-
Expand Down
2 changes: 1 addition & 1 deletion services/dokuwiki.nix
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ in {
};
plugin.oauthkeycloak = {
key = get_secret "dokuwiki/keycloak_key";
openidurl = "https://sso.chaos.jetzt/auth/realms/${if isDev then "dev" else "chaos-jetzt"}/.well-known/openid-configuration";
openidurl = "https://sso${lib.optionalString isDev ".dev"}.chaos.jetzt/auth/realms/${if isDev then "dev" else "chaos-jetzt"}/.well-known/openid-configuration";
};
};

Expand Down
160 changes: 160 additions & 0 deletions services/keycloak/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
{ pkgs
, config
, lib
, baseDomain
, isDev
, ...
}:

let
sso_domain = "sso.${baseDomain}";

populate_content = pkgs.writeText "populate_content.ldif" ''
dn: dc=chaos, dc=jetzt
dc: chaos
o: chaos.jetzt
objectClass: top
objectclass: organization
objectclass: dcObject
dn: ou=People,dc=chaos,dc=jetzt
changetype: add
objectClass: organizationalUnit
dn: ou=Groups,dc=chaos,dc=jetzt
changetype: add
objectClass: organizationalUnit
'';
init_ldap = pkgs.writeShellScript "init-ldap" ''
export PATH=${config.services.openldap.package}/bin:$PATH
export LDAP_ALREADY_EXISTS=68
ldapadd -c -Y EXTERNAL -H ldapi:/// -f ${populate_content}
ret=$?
if [[ $ret -eq $LDAP_ALREADY_EXISTS ]]; then
echo "Everything already exists"
exit 0
fi
exit $ret
'';
in {
sops.secrets = {
"keycloak/db_password" = {};
"ldap/admin_password".owner = config.services.openldap.user;
};
services.keycloak = {
enable = true;
database = {
createLocally = true;
host = "localhost";
name = "keycloak";
passwordFile = config.sops.secrets."keycloak/db_password".path;
type = "postgresql";
};
settings = {
hostname = sso_domain;
http-host = "127.0.0.1";
# Since we're comming from 12.x
http-relative-path = "/auth";
http-port = 8081;
https-port = 8443;
proxy = "edge";
spi-theme-welcome-theme = "chaos-jetzt";
spi-connections-jpa-legacy-migration-strategy = "update";
};
plugins = [ pkgs.keycloak-registration-captcha ];
themes.cj-keycloak-theme = pkgs.cj-keycloak-theme;
};

services.openldap = {
enable = true;
urlList = [
"ldap:///"
"ldapi:///"
];
settings = {
attrs.olcLogLevel = [ "stats" ];
children = let
root_access = "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth";
in{
"cn=schema".includes = [
"${pkgs.openldap}/etc/schema/core.ldif"
"${pkgs.openldap}/etc/schema/cosine.ldif"
"${pkgs.openldap}/etc/schema/nis.ldif"
"${pkgs.openldap}/etc/schema/inetorgperson.ldif"
];
"olcDatabase={-1}frontend".attrs = {
objectClass = [ "olcDatabaseConfig" "olcFrontendConfig" ];
olcDatabase = "{-1}frontend";
olcSizeLimit = "500";
# Allows the local root user to see the running config
# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config
olcAccess = [
"{0}to * by ${root_access} manage by * break"
"{1}to dn.exact=\"\" by * read"
"{2}to dn.base=\"cn=Subschema\" by * read"
];
structuralObjectClass = "olcDatabaseConfig";
};
/* "olcBackend={0}mdb".attrs = {
objectClass = "olcBackendConfig";
olcBackend = "{0}config";
}; */
"olcDatabase={0}config".attrs = {
objectClass = "olcDatabaseConfig";
olcDatabase = "{0}config";
# Allows the local root user to see the running config
# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config
olcAccess = [
"{0}to * by ${root_access} manage by * break"
];
};
"olcDatabase={1}mdb".attrs = {
objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];

olcDatabase = "{1}mdb";
olcDbDirectory = "/var/lib/openldap/data";

olcSuffix = "dc=chaos,dc=jetzt";

olcRootDN = "cn=admin,dc=chaos,dc=jetzt";
olcRootPW.path = config.sops.secrets."ldap/admin_password".path;

olcLastMod = "TRUE";
olcdbcheckpoint = "512 30";

olcDbIndex = [
"objectClass eq"
"cn,uid eq"
"uidNumber,gidNumber eq"
"member,memberUid eq"
];
olcAccess = [
''{0}to attrs=userPassword by self write by anonymous auth by * none''
''{1}to attrs=shadowLastChange by self write by * read''
];
};
};
};
};

systemd.services.openldap.serviceConfig.ExecStartPost = [
"!${init_ldap}"
];

services.nginx = {
enable = true;
virtualHosts."${sso_domain}" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://127.0.0.1:${toString config.services.keycloak.settings.http-port}";
locations."= /".return = "307 ${config.services.keycloak.settings.http-relative-path}/realms/${if !isDev then "chaos-jetzt" else "dev"}/account/";
};
};

/*
NOTE(@e1mo): Gripes with the keycloak module
- `database.createLocaly` doesn't respect username
- `initialAdminPassword` can't be a secret
- `pkgs.keycloak.plugins` can't be discovered via the search
*/
}

0 comments on commit 3151375

Please sign in to comment.