diff --git a/paris-container.nix b/paris-container.nix index 2bd379e..f7c7f0e 100644 --- a/paris-container.nix +++ b/paris-container.nix @@ -15,6 +15,59 @@ in { description = "Directory at which to store server state."; }; + ldap = { + image = mkOption { + type = str; + description = "Authentik LDAP outpost Docker image."; + }; + + domain = mkOption { + type = str; + description = + "Domain for which data is served. Only used for internal mapping."; + }; + + authentik-host = mkOption { + type = str; + description = "Hostname of the LDAP outpost provider."; + default = "authentik.${toplevel.config.fudo.mail.primary-domain}"; + }; + + outpost-token = mkOption { + type = str; + description = "Token with which to authenticate to the Authentik host."; + }; + + bind-dn = mkOption { + type = str; + description = "DN as which to bind with the LDAP server."; + }; + + bind-token-file = mkOption { + type = str; + description = + "File containing token with which to bind with the LDAP server."; + }; + + base = mkOption { + type = str; + description = "Base of the LDAP server."; + example = "dc=fudo,dc=org"; + }; + + user-ou = mkOption { + type = str; + description = "Organizational unit containing users."; + default = "ou=users"; + }; + + group-ou = mkOption { + type = str; + description = "Organizational unit containing users."; + default = "ou=groups"; + }; + }; + networking = { interface = mkOption { type = str; @@ -59,6 +112,29 @@ in { systemd.tmpfiles.rules = [ "d ${cfg.state-directory}/home 0700 root root - -" ]; + fudo.secrets.host-secrets."${hostname}" = { + parisLdapEnv = { + source-file = pkgs.writeText "paris-ldap-proxy.env" + (concatStringsSep "\n" [ + "AUTHENTIK_HOST=${cfg.ldap.authentik-host}" + "AUTHENTIK_TOKEN=${cfg.ldap.outpost-token}" + "AUTHENTIK_INSECURE=false" + ]); + target-file = "/run/paris/ldap.env"; + }; + parisSssdEnv = { + source-file = pkgs.writeText "paris-sssd.env" + "LDAP_DEFAULT_AUTHTOKEN=${readFile cfg.ldap.bind-token-file}"; + }; + }; + + virtualisation.oci-containers.paris-ldap-proxy = { + image = cfg.ldap.image; + autoStart = true; + ports = [ "${cfg.ldap.port}:389" ]; + environmentFiles = [ hostSecrets.parisLdapEnv.target-file ]; + }; + containers.paris = { tmpfs = true; macvlans = [ cfg.networking.interface ]; @@ -74,6 +150,52 @@ in { environment.systemPackages = packages; + services.sssd = { + enable = true; + kcm = true; + environmentFile = hostSecrets.parisSssdEnv.target-file; + config = lib.generators.toINI { } { + sssd = { + config_file_version = 2; + reconnection_retries = 3; + sbus_timeout = 30; + services = [ "nss" "pam" "ssh" ]; + domains = [ cfg.ldap.domain ]; + }; + + pam = { reconnection_retries = 3; }; + + nss = { + filter_groups = "root"; + filter_users = "root"; + reconnection_retries = 3; + }; + + "domain/${cfg.ldap.domain}" = { + cache_credentials = true; + id_provider = "ldap"; + chpass_provider = "ldap"; + auth_provider = "ldap"; + access_provider = "ldap"; + + ldap_uri = "ldap://localhost:${cfg.ldap.port}"; + ldap_schema = "rfc2307bis"; + + ldap_search_base = cfg.ldap.base; + ldap_user_search_base = "${cfg.ldap.user-ou},${cfg.ldap.base}"; + ldap_group_search_base = "${cfg.ldap.group-ou},${cfg.ldap.base}"; + + ladp_user_object_class = "user"; + ldap_user_cn = "cn"; + ldap_group_object_class = "group"; + ldap_group_name = "cn"; + + ldap_default_bind_dn = cfg.ldap.bind-dn; + ldap_default_authtok = "$LDAP_DEFAULT_AUTHTOKEN"; + }; + }; + }; + networking = { defaultGateway = { address = config.networking.defaultGateway.address;