|
| 1 | +{ pkgs |
| 2 | +, config |
| 3 | +, lib |
| 4 | +, baseDomain |
| 5 | +, isDev |
| 6 | +, ... |
| 7 | +}: |
| 8 | + |
| 9 | +let |
| 10 | + sso_domain = "sso.${baseDomain}"; |
| 11 | + |
| 12 | + populate_content = pkgs.writeText "populate_content.ldif" '' |
| 13 | + dn: dc=chaos, dc=jetzt |
| 14 | + dc: chaos |
| 15 | + o: chaos.jetzt |
| 16 | + objectClass: top |
| 17 | + objectclass: organization |
| 18 | + objectclass: dcObject |
| 19 | +
|
| 20 | + dn: ou=People,dc=chaos,dc=jetzt |
| 21 | + changetype: add |
| 22 | + objectClass: organizationalUnit |
| 23 | +
|
| 24 | + dn: ou=Groups,dc=chaos,dc=jetzt |
| 25 | + changetype: add |
| 26 | + objectClass: organizationalUnit |
| 27 | + ''; |
| 28 | + init_ldap = pkgs.writeShellScript "init-ldap" '' |
| 29 | + export PATH=${config.services.openldap.package}/bin:$PATH |
| 30 | + export LDAP_ALREADY_EXISTS=68 |
| 31 | + ldapadd -c -Y EXTERNAL -H ldapi:/// -f ${populate_content} |
| 32 | + ret=$? |
| 33 | + if [[ $ret -eq $LDAP_ALREADY_EXISTS ]]; then |
| 34 | + echo "Everything already exists" |
| 35 | + exit 0 |
| 36 | + fi |
| 37 | + exit $ret |
| 38 | + ''; |
| 39 | +in { |
| 40 | + sops.secrets = { |
| 41 | + "keycloak/db_password" = {}; |
| 42 | + "ldap/admin_password".owner = config.services.openldap.user; |
| 43 | + }; |
| 44 | + services.keycloak = { |
| 45 | + enable = true; |
| 46 | + database = { |
| 47 | + createLocally = true; |
| 48 | + host = "localhost"; |
| 49 | + name = "keycloak"; |
| 50 | + passwordFile = config.sops.secrets."keycloak/db_password".path; |
| 51 | + type = "postgresql"; |
| 52 | + }; |
| 53 | + settings = { |
| 54 | + hostname = sso_domain; |
| 55 | + http-host = "127.0.0.1"; |
| 56 | + # Since we're comming from 12.x |
| 57 | + http-relative-path = "/auth"; |
| 58 | + http-port = 8081; |
| 59 | + https-port = 8443; |
| 60 | + proxy = "edge"; |
| 61 | + spi-theme-welcome-theme = "chaos-jetzt"; |
| 62 | + spi-connections-jpa-legacy-migration-strategy = "update"; |
| 63 | + }; |
| 64 | + plugins = [ pkgs.keycloak-registration-captcha ]; |
| 65 | + themes.cj-keycloak-theme = pkgs.cj-keycloak-theme; |
| 66 | + }; |
| 67 | + |
| 68 | + services.openldap = { |
| 69 | + enable = true; |
| 70 | + urlList = [ |
| 71 | + "ldap:///" |
| 72 | + "ldapi:///" |
| 73 | + ]; |
| 74 | + settings = { |
| 75 | + attrs.olcLogLevel = [ "stats" ]; |
| 76 | + children = let |
| 77 | + root_access = "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth"; |
| 78 | + in{ |
| 79 | + "cn=schema".includes = [ |
| 80 | + "${pkgs.openldap}/etc/schema/core.ldif" |
| 81 | + "${pkgs.openldap}/etc/schema/cosine.ldif" |
| 82 | + "${pkgs.openldap}/etc/schema/nis.ldif" |
| 83 | + "${pkgs.openldap}/etc/schema/inetorgperson.ldif" |
| 84 | + ]; |
| 85 | + "olcDatabase={-1}frontend".attrs = { |
| 86 | + objectClass = [ "olcDatabaseConfig" "olcFrontendConfig" ]; |
| 87 | + olcDatabase = "{-1}frontend"; |
| 88 | + olcSizeLimit = "500"; |
| 89 | + # Allows the local root user to see the running config |
| 90 | + # ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config |
| 91 | + olcAccess = [ |
| 92 | + "{0}to * by ${root_access} manage by * break" |
| 93 | + "{1}to dn.exact=\"\" by * read" |
| 94 | + "{2}to dn.base=\"cn=Subschema\" by * read" |
| 95 | + ]; |
| 96 | + structuralObjectClass = "olcDatabaseConfig"; |
| 97 | + }; |
| 98 | + /* "olcBackend={0}mdb".attrs = { |
| 99 | + objectClass = "olcBackendConfig"; |
| 100 | + olcBackend = "{0}config"; |
| 101 | + }; */ |
| 102 | + "olcDatabase={0}config".attrs = { |
| 103 | + objectClass = "olcDatabaseConfig"; |
| 104 | + olcDatabase = "{0}config"; |
| 105 | + # Allows the local root user to see the running config |
| 106 | + # ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config |
| 107 | + olcAccess = [ |
| 108 | + "{0}to * by ${root_access} manage by * break" |
| 109 | + ]; |
| 110 | + }; |
| 111 | + "olcDatabase={1}mdb".attrs = { |
| 112 | + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; |
| 113 | + |
| 114 | + olcDatabase = "{1}mdb"; |
| 115 | + olcDbDirectory = "/var/lib/openldap/data"; |
| 116 | + |
| 117 | + olcSuffix = "dc=chaos,dc=jetzt"; |
| 118 | + |
| 119 | + olcRootDN = "cn=admin,dc=chaos,dc=jetzt"; |
| 120 | + olcRootPW.path = config.sops.secrets."ldap/admin_password".path; |
| 121 | + |
| 122 | + olcLastMod = "TRUE"; |
| 123 | + olcdbcheckpoint = "512 30"; |
| 124 | + |
| 125 | + olcDbIndex = [ |
| 126 | + "objectClass eq" |
| 127 | + "cn,uid eq" |
| 128 | + "uidNumber,gidNumber eq" |
| 129 | + "member,memberUid eq" |
| 130 | + ]; |
| 131 | + olcAccess = [ |
| 132 | + ''{0}to attrs=userPassword by self write by anonymous auth by * none'' |
| 133 | + ''{1}to attrs=shadowLastChange by self write by * read'' |
| 134 | + ]; |
| 135 | + }; |
| 136 | + }; |
| 137 | + }; |
| 138 | + }; |
| 139 | + |
| 140 | + systemd.services.openldap.serviceConfig.ExecStartPost = [ |
| 141 | + "!${init_ldap}" |
| 142 | + ]; |
| 143 | + |
| 144 | + services.nginx = { |
| 145 | + enable = true; |
| 146 | + virtualHosts."${sso_domain}" = { |
| 147 | + enableACME = true; |
| 148 | + forceSSL = true; |
| 149 | + locations."/".proxyPass = "http://127.0.0.1:${toString config.services.keycloak.settings.http-port}"; |
| 150 | + locations."= /".return = "307 ${config.services.keycloak.settings.http-relative-path}/realms/${if !isDev then "chaos-jetzt" else "dev"}/account/"; |
| 151 | + }; |
| 152 | + }; |
| 153 | + |
| 154 | + /* |
| 155 | + NOTE(@e1mo): Gripes with the keycloak module |
| 156 | + - `database.createLocaly` doesn't respect username |
| 157 | + - `initialAdminPassword` can't be a secret |
| 158 | + - `pkgs.keycloak.plugins` can't be discovered via the search |
| 159 | + */ |
| 160 | +} |
0 commit comments