From 5411c530226d4b8a6e474454c28aaa9816ed6082 Mon Sep 17 00:00:00 2001 From: niten Date: Mon, 7 Feb 2022 14:08:34 -0800 Subject: [PATCH] About to make changes to Grafana LDAP --- lib/fudo/backplane.nix | 34 ++++++----- lib/fudo/grafana.nix | 136 +++++++++++++++++++++++++++++++++++------ lib/fudo/jabber.nix | 9 ++- lib/fudo/postgres.nix | 30 +++++---- lib/fudo/powerdns.nix | 20 +++++- lib/instance.nix | 6 ++ 6 files changed, 180 insertions(+), 55 deletions(-) diff --git a/lib/fudo/backplane.nix b/lib/fudo/backplane.nix index 795e40e..a197766 100644 --- a/lib/fudo/backplane.nix +++ b/lib/fudo/backplane.nix @@ -89,6 +89,7 @@ in { host-secrets.backplane-host-auth.target-file; FUDO_SERVICE_PASSWD_FILE = host-secrets.backplane-service-auth.target-file; + # GUILE_AUTO_COMPILE = "0"; }; sites.${cfg.backplane-hostname} = { @@ -97,31 +98,32 @@ in { site-config = { auth_method = "external"; extauth_program = + # "${pkgs.guile}/bin/guile -s /run/backplane-auth.scm"; "${pkgs.guile}/bin/guile -s ${pkgs.backplane-auth}/backplane-auth.scm"; extauth_pool_size = 3; - auth_use_cache = true; + auth_use_cache = false; modules = { mod_adhoc = {}; - mod_caps = {}; - mod_carboncopy = {}; - mod_client_state = {}; + # mod_caps = {}; + # mod_carboncopy = {}; + # mod_client_state = {}; mod_configure = {}; - mod_disco = {}; + # mod_disco = {}; mod_fail2ban = {}; - mod_last = {}; + # mod_last = {}; mod_offline.access_max_user_messages = 5000; mod_ping = {}; - mod_pubsub = { - access_createnode = "pubsub_createnode"; - ignore_pep_from_offline = true; - last_item_cache = false; - plugins = [ - "flat" - "pep" - ]; - }; - mod_roster = {}; + # mod_pubsub = { + # access_createnode = "pubsub_createnode"; + # ignore_pep_from_offline = true; + # last_item_cache = false; + # plugins = [ + # "flat" + # "pep" + # ]; + # }; + # mod_roster = {}; mod_stream_mgmt = {}; mod_time = {}; mod_version = {}; diff --git a/lib/fudo/grafana.nix b/lib/fudo/grafana.nix index d4763d2..3a2f873 100644 --- a/lib/fudo/grafana.nix +++ b/lib/fudo/grafana.nix @@ -9,6 +9,58 @@ let hostname = config.instance.hostname; domain-name = config.fudo.hosts.${hostname}.domain; + host-secrets = config.fudo.secrets.host-secrets.${hostname}; + + datasourceOpts = { name, ... }: { + options = with types; { + url = mkOption { + type = str; + description = "Datasource URL."; + }; + + type = mkOption { + type = enum [ "prometheus" "loki" ]; + description = "Type of the datasource."; + }; + + name = mkOption { + type = str; + description = "Name of the datasource."; + default = name; + }; + + default = mkOption { + type = bool; + description = "Use this datasource as the default while querying."; + default = false; + }; + }; + }; + + ldapOpts = { + options = with types; { + hosts = mkOption { + type = listOf str; + description = "LDAP server hostnames."; + }; + + bind-dn = mkOption { + type = str; + description = "DN as which to bind with the LDAP server."; + }; + + bind-passwd = mkOption { + type = str; + description = "Password with which to bind to the LDAP server."; + }; + + base-dn = mkOption { + type = str; + description = "DN under which to search for users."; + }; + }; + }; + in { options.fudo.metrics.grafana = with types; { @@ -43,6 +95,12 @@ in { description = "Address from which mail will be sent (i.e. 'from' address)."; default = "${toplevel.config.fudo.grafana.smtp.username}@${domain-name}"; }; + + domain = mkOption { + type = str; + description = "Domain of the SMTP server."; + default = toplevel.config.instance.local-domain; + }; }; database = { @@ -67,6 +125,12 @@ in { }; }; + ldap = mkOption { + type = nullOr (submodule ldapOpts); + description = ""; + default = null; + }; + admin-password-file = mkOption { type = str; description = "Path to a file containing the admin user's password."; @@ -77,10 +141,10 @@ in { description = "Path to a file containing the server's secret key, used for signatures."; }; - prometheus-hosts = mkOption { - type = listOf str; - description = "A list of URLs to prometheus data sources."; - default = []; + datasources = mkOption { + type = attrsOf (submodule datasourceOpts); + description = "A list of datasources supplied to Grafana."; + default = {}; }; state-directory = mkOption { @@ -93,11 +157,26 @@ in { }; config = mkIf cfg.enable { - systemd.tmpfiles.rules = let - grafana-user = config.systemd.services.grafana.serviceConfig.User; - in [ - "d ${cfg.state-directory} 0700 ${grafana-user} - - -" - ]; + systemd = { + tmpfiles.rules = let + grafana-user = config.systemd.services.grafana.serviceConfig.User; + in [ + "d ${cfg.state-directory} 0700 ${grafana-user} - - -" + ]; + + services.grafana.serviceConfig = { + EnvironmentFile = host-secrets.grafana-environment-file.target-file; + }; + }; + + fudo.secrets.host-secrets.${hostname}.grafana-environment-file = { + source-file = pkgs.writeText "grafana.env" '' + ${optionalString (cfg.ldap != null) + ''GRAFANA_LDAP_BIND_PASSWD="${cfg.ldap.bind-passwd}"''} + ''; + target-file = "/run/metrics/grafana/auth-bind.passwd"; + user = config.systemd.services.grafana.serviceConfig.User; + }; services = { nginx = { @@ -133,12 +212,30 @@ in { smtp = { enable = true; - fromAddress = "metrics@fudo.org"; + # TODO: create system user as necessary + fromAddress = "${cfg.smtp.username}@${cfg.smtp.domain}"; host = "${cfg.smtp.hostname}:25"; user = cfg.smtp.username; passwordFile = cfg.smtp.password-file; }; + extraOptions = mkIf (cfg.ldap != null) (let + config-file = pkgs.writeText "grafana-ldap.toml" '' + [[servers]] + host = "${concatStringsSep " " cfg.ldap.hosts}" + port = 389 + start_tls = true + bind_dn = "${cfg.ldap.bind-dn}" + bind_password = "''${GRAFANA_LDAP_BIND_PASSWD}" + search_filter = "(uid=%s)" + search_base_dns = [ "${cfg.ldap.base-dn}" ] + ''; + in { + AUTH_LDAP_ENABLED = "true"; + AUTH_LDAP_ALLOW_SIGN_UP = "false"; + AUTH_LDAP_CONFIG_FILE = config-file; + }); + database = { host = cfg.database.hostname; name = cfg.database.name; @@ -147,15 +244,16 @@ in { type = "postgres"; }; - provision.datasources = imap0 (i: host: { - editable = false; - isDefault = (i == 0); - name = builtins.trace "PROMETHEUS-HOST: ${host}" host; - type = "prometheus"; - url = let - scheme = if private-network then "http" else "https"; - in "${scheme}://${host}/"; - }) cfg.prometheus-hosts; + provision = { + enable = true; + datasources = let + make-datasource = datasource: { + editable = false; + isDefault = datasource.default; + inherit (datasource) name type url; + }; + in map make-datasource (attrValues cfg.datasources); + }; }; }; }; diff --git a/lib/fudo/jabber.nix b/lib/fudo/jabber.nix index 6b651d5..4b97cfc 100644 --- a/lib/fudo/jabber.nix +++ b/lib/fudo/jabber.nix @@ -96,7 +96,8 @@ let }; config-file = builtins.toJSON jabber-config; - in pkgs.writeText "ejabberd.config.yml.template" config-file; + in pkgs.lib.text.format-json-file + (pkgs.writeText "ejabberd.config.yml.template" config-file); enter-secrets = template: secrets: target: let secret-swappers = map @@ -170,13 +171,13 @@ in { }; log-level = mkOption { - type = int; + type = str; description = '' Log level at which to run the server. See: https://docs.ejabberd.im/admin/guide/troubleshooting/ ''; - default = 3; + default = "info"; }; state-directory = mkOption { @@ -212,8 +213,6 @@ in { in { acme.host-domains.${hostname} = mapAttrs' (site: siteOpts: nameValuePair siteOpts.hostname { - extra-domains = - (optional (siteOpts.hostname != host-fqdn) host-fqdn); local-copies.ejabberd = { user = cfg.user; group = cfg.group; diff --git a/lib/fudo/postgres.nix b/lib/fudo/postgres.nix index cad745f..5a4c612 100644 --- a/lib/fudo/postgres.nix +++ b/lib/fudo/postgres.nix @@ -127,7 +127,7 @@ let userDatabaseAccessSql = user: database: dbOpts: '' \c ${database} ${join-lines - (mapAttrsToList (userTableAccessSql user) dbOpts.entity-access)} + (mapAttrsToList (userTableAccessSql user) dbOpts.entity-access)} ''; userAccessSql = user: userOpts: join-lines (mapAttrsToList (userDatabaseAccessSql user) userOpts.databases); @@ -375,20 +375,24 @@ in { requires = [ "postgresql.target" ]; after = [ "postgresql.target" "postgresql-password-setter.target" ]; partOf = [ cfg.systemd-target ]; - script = let - allow-user-login = user: "ALTER ROLE ${user} WITH LOGIN;"; + wantedBy = [ "postgresql.target" ]; + serviceConfig = { + User = config.services.postgresql.superUser; + ExecStart = let + allow-user-login = user: "ALTER ROLE ${user} WITH LOGIN;"; - extra-settings-sql = pkgs.writeText "settings.sql" '' - ${concatStringsSep "\n" - (map allow-user-login (mapAttrsToList (key: val: key) cfg.users))} - ${usersAccessSql cfg.users} + extra-settings-sql = pkgs.writeText "settings.sql" '' + ${concatStringsSep "\n" + (map allow-user-login (mapAttrsToList (key: val: key) cfg.users))} + ${usersAccessSql cfg.users} + ''; + in pkgs.writeShellScript "postgresql-finalizer.sh" '' + ${pkgs.postgresql}/bin/psql --port ${ + toString config.services.postgresql.port + } -d postgres -f ${extra-settings-sql} + chgrp ${cfg.socket-group} ${cfg.socket-directory}/.s.PGSQL* ''; - in '' - ${pkgs.postgresql}/bin/psql --port ${ - toString config.services.postgresql.port - } -d postgres -f ${extra-settings-sql} - ${pkgs.coreutils}/bin/chgrp ${cfg.socket-group} ${cfg.socket-directory}/.s.PGSQL* - ''; + }; }; }; }; diff --git a/lib/fudo/powerdns.nix b/lib/fudo/powerdns.nix index 59314df..61e878f 100644 --- a/lib/fudo/powerdns.nix +++ b/lib/fudo/powerdns.nix @@ -21,6 +21,13 @@ let gpgsql-password=__PASSWORD__ gpgsql-dnssec=${if cfg.enable-dnssec then "yes" else "no"} gpgsql-extra-connection-parameters=sslmode=require + ${optionalString cfg.debug '' + log-dns-details + log-dns-queries + log-timestamp + loglevel=6 + query-logging + ''} ''; pdns-config-dir = pkgs.writeTextDir "pdns.conf" '' @@ -61,6 +68,7 @@ let networks-string = concatStringsSep " " (v4-nets ++ v6-nets); in ''"v=spf1 mx ${networks-string} -all"'')) (mkRecord "ns1.${domain-name}" "A" host-ip) + (mkRecord domain-name "A" host-ip) ] ++ (optional (domain.gssapi-realm != null) (mkRecord "_kerberos.${domain-name}" "TXT" ''"domain.gssapi-realm"'')) ++ @@ -158,6 +166,12 @@ in { default = true; }; + debug = mkOption { + type = bool; + description = "Enable verbose debugging."; + default = false; + }; + database = { host = mkOption { type = str; @@ -190,7 +204,10 @@ in { }; config = mkIf cfg.enable { - networking.firewall.allowedTCPPorts = [ cfg.port ]; + networking.firewall = { + allowedTCPPorts = [ cfg.port ]; + allowedUDPPorts = [ cfg.port ]; + }; users = { users.${cfg.user} = { @@ -308,7 +325,6 @@ in { "--chroot=${runtime-dir}" "--daemon=no" "--guardian=no" - "--disable-syslog" "--write-pid=no" "--config-dir=${pdns-config-dir}" ]); diff --git a/lib/instance.nix b/lib/instance.nix index 56bc1c1..5b91cdb 100644 --- a/lib/instance.nix +++ b/lib/instance.nix @@ -37,6 +37,12 @@ in { description = "Site name of the current local host."; }; + local-zone = mkOption { + type = nullOr str; + description = "Zone name of the current local host."; + default = null; + }; + local-admins = mkOption { type = listOf str; description = "List of users who should have admin access to the local host.";