/* Gonna use a priper nixos module for this */ { config, pkgs, lib, inputs, ... }: with lib; let cfg = config.services.skynet_ldap; in { # these are needed for teh program in question imports = [ ./acme.nix ./dns.nix ./nginx.nix ./ldap/ldap_backend.nix ]; options.services.skynet_ldap = { # options that need to be passed in to make this work enable = mkEnableOption "Skynet LDAP service"; host = { ip = mkOption { type = types.str; }; name = mkOption { type = types.str; }; }; domain = { tld = mkOption { type = types.str; default = "ie"; }; base = mkOption { type = types.str; default = "skynet"; }; sub = mkOption { type = types.str; default = "account"; }; }; frontend.port = mkOption { type = types.port; default = 8888; }; base = mkOption { type = types.str; default = "dc=skynet,dc=ie"; }; }; config = mkIf cfg.enable { # passthrough to the backend services.ldap_backend = { enable = true; host.ip = cfg.host.ip; host.name = cfg.host.name; }; # after changing teh password openldap.service has to be restarted age.secrets.ldap_pw = { file = ../secrets/ldap/pw.age; mode = "440"; owner = "openldap"; group = "openldap"; }; skynet_dns.records = [ {record=cfg.domain.sub; r_type="CNAME"; value=cfg.host.name;} ]; # firewall on teh computer itself networking.firewall.allowedTCPPorts = [ 389 636 ]; services.nginx.virtualHosts = { "${cfg.domain.sub}.${cfg.domain.base}.${cfg.domain.tld}" = { forceSSL = true; useACMEHost = "skynet"; locations."/" = { root = "${inputs.skynet_ldap_frontend.defaultPackage."x86_64-linux"}"; # https://stackoverflow.com/a/38238001 extraConfig = '' if ($request_uri ~ ^/(.*)\.html) { return 302 /$1; } try_files $uri $uri.html $uri/ =404; ''; }; }; }; # using https://nixos.wiki/wiki/OpenLDAP for base config systemd.services.openldap = { wants = [ "acme-${cfg.domain.base}.service" ]; after = [ "acme-${cfg.domain.base}.service" ]; }; users.groups.acme.members = [ "openldap" ]; services.openldap = { # backup /var/lib/openldap/slapd.d enable = true; /* enable plain and secure connections */ urlList = [ "ldap:///" "ldaps:///" ]; settings = { attrs = { olcLogLevel = "conns config"; /* settings for acme ssl */ olcTLSCACertificateFile = "/var/lib/acme/${cfg.domain.base}/full.pem"; olcTLSCertificateFile = "/var/lib/acme/${cfg.domain.base}/cert.pem"; olcTLSCertificateKeyFile = "/var/lib/acme/${cfg.domain.base}/key.pem"; # got teh ciphers from https://access.redhat.com/articles/1474813 # the ones provided on the nixos page didnt work olcTLSCipherSuite = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:!RC4:HIGH:!MD5:!aNULL:!EDH:!EXP:!SSLV2:!eNULL"; olcTLSCRLCheck = "none"; olcTLSVerifyClient = "never"; olcTLSProtocolMin = "3.3"; # make it so it can return up to 2000 results ar once, more than twice our total records for users olcSizeLimit = "2000"; }; children = { "cn=schema".includes = [ "${pkgs.openldap}/etc/schema/core.ldif" "${pkgs.openldap}/etc/schema/cosine.ldif" "${pkgs.openldap}/etc/schema/inetorgperson.ldif" "${pkgs.openldap}/etc/schema/nis.ldif" ./ldap/openssh-lpk.ldif ./ldap/skMemberOf.ldif ]; "cn=modules".attrs = { objectClass = [ "olcModuleList" ]; cn = "modules"; olcModuleLoad = ["dynlist" "memberof" "refint" "pw-sha2"]; }; "olcDatabase={-1}frontend".attrs = { objectClass = [ "olcDatabaseConfig" "olcFrontendConfig" ]; olcPasswordHash = "{SSHA512}"; }; "olcDatabase={1}mdb" = { attrs = { objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; olcDatabase = "{1}mdb"; olcDbDirectory = "/var/lib/openldap/data"; olcSuffix = cfg.base; /* your admin account, do not use writeText on a production system */ olcRootDN = "cn=admin,${cfg.base}"; olcRootPW.path = config.age.secrets.ldap_pw.path; #olcOverlay = "memberof"; olcAccess = [ /* custom access rules for userPassword attributes */ ''{0}to attrs=userPassword by dn.exact="uid=ldap_api,ou=users,dc=skynet,dc=ie" manage by self write by anonymous auth by * none'' ''{1}to attrs=mail,sshPublicKey,cn,sn,skDiscord by dn.exact="uid=ldap_api,ou=users,dc=skynet,dc=ie" manage by self write by * read'' /* allow read on anything else */ ''{2}to * by dn.exact="uid=ldap_api,ou=users,dc=skynet,dc=ie" manage by * read'' ]; }; # https://blog.oddbit.com/post/2013-07-22-generating-a-membero/ children = { "olcOverlay=dynlist".attrs = { objectClass = [ "olcOverlayConfig" "olcDynamicList" ]; olcOverlay = "dynlist"; olcDlAttrSet = "skPerson labeledURI skMemberOf"; }; "olcOverlay=memberof".attrs = { objectClass = [ "olcOverlayConfig" "olcMemberOf" "olcConfig" "top" ]; olcOverlay = "memberof"; olcMemberOfDangling = "ignore"; olcMemberOfRefInt = "TRUE"; olcMemberOfGroupOC = "groupOfNames"; olcMemberOfMemberAD = "member"; olcMemberOfMemberOfAD = "memberOf"; }; }; }; }; }; }; }; }