]> git.immae.eu Git - perso/Immae/Config/Nix.git/commitdiff
Add openldap replication
authorIsmaël Bouya <ismael.bouya@normalesup.org>
Sun, 8 Dec 2019 15:22:56 +0000 (16:22 +0100)
committerIsmaël Bouya <ismael.bouya@normalesup.org>
Sun, 8 Dec 2019 15:22:56 +0000 (16:22 +0100)
modules/private/databases/openldap/default.nix
modules/private/databases/openldap/eldiron_schemas.nix [new file with mode: 0644]
modules/private/databases/openldap_replication.nix [new file with mode: 0644]
modules/private/default.nix
modules/private/monitoring/default.nix
modules/private/monitoring/objects_backup-2.nix
modules/private/monitoring/objects_common.nix
modules/private/monitoring/plugins/check_openldap_replication [new file with mode: 0755]
modules/private/system/backup-2.nix

index 9f72b297df0383abff8ad15102133a8ac288fcd6..22f6f7b3de3b8b5d9223b6034b3a203c32cc6a1d 100644 (file)
@@ -2,22 +2,9 @@
 let
   cfg = config.myServices.databases.openldap;
   ldapConfig = let
-    kerberosSchema = pkgs.fetchurl {
-      url = "https://raw.githubusercontent.com/krb5/krb5/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema";
-      sha256 = "17fnkkf6s3lznsl7wp6914pqsc78d038rh38l638big8z608ksww";
-    };
-    puppetSchema = pkgs.fetchurl {
-      url = "https://raw.githubusercontent.com/puppetlabs/puppet/master/ext/ldap/puppet.schema";
-      sha256 = "11bjf5zfvqlim7p9vddcafs0wiq3v8ys77x8h6fbp9c6bdfh0awh";
-    };
+    eldiron_schemas = pkgs.callPackage ./eldiron_schemas.nix {};
   in ''
-    include         ${pkgs.openldap}/etc/schema/core.schema
-    include         ${pkgs.openldap}/etc/schema/cosine.schema
-    include         ${pkgs.openldap}/etc/schema/inetorgperson.schema
-    include         ${pkgs.openldap}/etc/schema/nis.schema
-    include         ${puppetSchema}
-    include         ${kerberosSchema}
-    include         ${./immae.schema}
+    ${eldiron_schemas}
 
     pidfile         ${cfg.pids.pid}
     argsfile        ${cfg.pids.args}
@@ -33,6 +20,10 @@ let
     directory       ${cfg.dataDir}
     overlay         memberof
 
+    moduleload      syncprov
+    overlay         syncprov
+    syncprov-checkpoint 100 10
+
     TLSCertificateFile    ${config.security.acme.directory}/ldap/cert.pem
     TLSCertificateKeyFile ${config.security.acme.directory}/ldap/key.pem
     TLSCACertificateFile  ${config.security.acme.directory}/ldap/fullchain.pem
@@ -126,14 +117,6 @@ in
     users.users.openldap.extraGroups = [ "keys" ];
     networking.firewall.allowedTCPPorts = [ 636 389 ];
 
-    services.cron = {
-      systemCronJobs = [
-        ''
-          35 1,13 * * * root ${pkgs.openldap}/bin/slapcat -v -b "dc=immae,dc=eu" -f ${pkgs.writeText "slapd.conf" ldapConfig} -l ${cfg.dataDir}/backup.ldif | ${pkgs.gnugrep}/bin/grep -v "^# id=[0-9a-f]*$"
-        ''
-      ];
-    };
-
     security.acme.certs."ldap" = config.myServices.databasesCerts // {
       user = "openldap";
       group = "openldap";
diff --git a/modules/private/databases/openldap/eldiron_schemas.nix b/modules/private/databases/openldap/eldiron_schemas.nix
new file mode 100644 (file)
index 0000000..7a29988
--- /dev/null
@@ -0,0 +1,21 @@
+{ fetchurl, openldap }:
+let
+  kerberosSchema = fetchurl {
+    url = "https://raw.githubusercontent.com/krb5/krb5/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema";
+    sha256 = "17fnkkf6s3lznsl7wp6914pqsc78d038rh38l638big8z608ksww";
+  };
+  puppetSchema = fetchurl {
+    url = "https://raw.githubusercontent.com/puppetlabs/puppet/master/ext/ldap/puppet.schema";
+    sha256 = "11bjf5zfvqlim7p9vddcafs0wiq3v8ys77x8h6fbp9c6bdfh0awh";
+  };
+  schemas = [
+    "${openldap}/etc/schema/core.schema"
+    "${openldap}/etc/schema/cosine.schema"
+    "${openldap}/etc/schema/inetorgperson.schema"
+    "${openldap}/etc/schema/nis.schema"
+    puppetSchema
+    kerberosSchema
+    ./immae.schema
+  ];
+in
+  builtins.concatStringsSep "\n" (map (v: "include         ${v}") schemas)
diff --git a/modules/private/databases/openldap_replication.nix b/modules/private/databases/openldap_replication.nix
new file mode 100644 (file)
index 0000000..c0c16e6
--- /dev/null
@@ -0,0 +1,164 @@
+{ pkgs, config, myconfig, lib, ... }:
+let
+  cfg = config.myServices.databasesReplication.openldap;
+  eldiron_schemas = pkgs.callPackage ./openldap/eldiron_schemas.nix {};
+  ldapConfig = hcfg: name: pkgs.writeText "slapd.conf" ''
+    ${eldiron_schemas}
+    pidfile   /run/slapd_${name}/slapd.pid
+    argsfile  /run/slapd_${name}/slapd.args
+
+    moduleload  back_hdb
+    backend     hdb
+    database    hdb
+
+    suffix    "${hcfg.base}"
+    rootdn    "cn=root,${hcfg.base}"
+    directory ${cfg.base}/${name}/openldap
+
+    index   objectClass       eq
+    index   uid               pres,eq
+    index   entryUUID         eq
+
+    include ${config.secrets.location}/openldap_replication/${name}/replication_config
+    '';
+in
+{
+  options.myServices.databasesReplication.openldap = {
+    enable = lib.mkEnableOption "Enable openldap replication";
+    base = lib.mkOption {
+      type = lib.types.path;
+      description = ''
+        Base path to put the replications
+        '';
+    };
+    hosts = lib.mkOption {
+      default = {};
+      description = ''
+        Hosts to backup
+        '';
+      type = lib.types.attrsOf (lib.types.submodule {
+        options = {
+          package = lib.mkOption {
+            type = lib.types.package;
+            default = pkgs.openldap;
+            description = ''
+              Openldap package for this host
+            '';
+          };
+          url = lib.mkOption {
+            type = lib.types.str;
+            description = ''
+              Host to connect to
+              '';
+          };
+          base = lib.mkOption {
+            type = lib.types.str;
+            description = ''
+              Base DN to replicate
+              '';
+          };
+          dn = lib.mkOption {
+            type = lib.types.str;
+            description = ''
+              DN to use
+              '';
+          };
+          password = lib.mkOption {
+            type = lib.types.str;
+            description = ''
+              Password to use
+              '';
+          };
+        };
+      });
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    users.users.openldap = {
+      description = "Openldap database user";
+      group = "openldap";
+      uid = config.ids.uids.openldap;
+      extraGroups = [ "keys" ];
+    };
+    users.groups.openldap.gid = config.ids.gids.openldap;
+
+    secrets.keys = lib.flatten (lib.mapAttrsToList (name: hcfg: [
+      {
+        dest = "openldap_replication/${name}/replication_config";
+        user = "openldap";
+        group = "openldap";
+        permissions = "0400";
+        text = ''
+          syncrepl rid=000
+                  provider=${hcfg.url}
+                  type=refreshAndPersist
+                  searchbase="${hcfg.base}"
+                  retry="5 10 300 +"
+                  attrs="*,+"
+                  schemachecking=off
+                  bindmethod=simple
+                  binddn="${hcfg.dn}"
+                  credentials="${hcfg.password}"
+          '';
+      }
+      {
+        dest = "openldap_replication/${name}/replication_password";
+        user = "openldap";
+        group = "openldap";
+        permissions = "0400";
+        text = hcfg.password;
+      }
+    ]) cfg.hosts);
+
+    services.cron = {
+      enable = true;
+      systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg:
+        let
+          dataDir = "${cfg.base}/${name}/openldap";
+          backupDir = "${cfg.base}/${name}/openldap_backup";
+          backup_script = pkgs.writeScript "backup_openldap_${name}" ''
+              #!${pkgs.stdenv.shell}
+
+              ${hcfg.package}/bin/slapcat -b "${hcfg.base}" -f ${ldapConfig hcfg name} -l ${backupDir}/$(${pkgs.coreutils}/bin/date -Iseconds).ldif
+            '';
+          u = pkgs.callPackage ./utils.nix {};
+          cleanup_script = pkgs.writeScript "cleanup_openldap_${name}" (u.exponentialDumps "ldif" backupDir);
+        in [
+          "0 22,4,10,16 * * * root ${backup_script}"
+          "0 3 * * * root ${cleanup_script}"
+        ]) cfg.hosts);
+    };
+
+    system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg:
+      lib.attrsets.nameValuePair "openldap_replication_${name}" {
+        deps = [ "users" "groups" ];
+        text = ''
+          install -m 0700 -o openldap -g openldap -d ${cfg.base}/${name}/openldap
+          install -m 0700 -o openldap -g openldap -d ${cfg.base}/${name}/openldap_backup
+          '';
+      }) cfg.hosts;
+
+    systemd.services = lib.attrsets.mapAttrs' (name: hcfg:
+      let
+        dataDir = "${cfg.base}/${name}/openldap";
+      in
+      lib.attrsets.nameValuePair "openldap_backup_${name}" {
+        description = "Openldap replication for ${name}";
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
+        unitConfig.RequiresMountsFor = dataDir;
+
+        preStart = ''
+          mkdir -p /run/slapd_${name}
+          chown -R "openldap:openldap" /run/slapd_${name}
+        '';
+
+        serviceConfig = {
+          ExecStart = "${hcfg.package}/libexec/slapd -d 0 -u openldap -g openldap -f ${ldapConfig hcfg name}";
+        };
+    }) cfg.hosts;
+  };
+}
+
+
index 1d0f1a9fe2ee2e01ba73c0ae271f67a8684c6938..29bf2af06cd081947cf91411b5c2eeafaecec637 100644 (file)
@@ -13,6 +13,7 @@ set = {
   postgresqlReplication = ./databases/postgresql_replication.nix;
   mariadbReplication = ./databases/mariadb_replication.nix;
   redisReplication = ./databases/redis_replication.nix;
+  openldapReplication = ./databases/openldap_replication.nix;
 
   websites = ./websites;
   atenInte = ./websites/aten/integration.nix;
index b3f8cbee734cf53f3c672e88171a2f036282fc4d..e44b127488e3691090721c9d856dbde2534af985 100644 (file)
@@ -22,6 +22,9 @@ let
     wrapProgram $out/check_mysql_replication --prefix PATH : ${lib.makeBinPath [
       pkgs.gnugrep pkgs.gnused pkgs.coreutils pkgs.mariadb
     ]}
+    wrapProgram $out/check_openldap_replication --prefix PATH : ${lib.makeBinPath [
+      pkgs.gnugrep pkgs.gnused pkgs.coreutils pkgs.openldap
+    ]}
     '';
   toObjects = pkgs.callPackage ./to_objects.nix {};
   commonConfig = {
@@ -42,7 +45,7 @@ let
     let
       specific_file = ./. + "/objects_" + name + ".nix";
     in
-      lib.attrsets.optionalAttrs (builtins.pathExists specific_file) (pkgs.callPackage specific_file {});
+      lib.attrsets.optionalAttrs (builtins.pathExists specific_file) (pkgs.callPackage specific_file { inherit config; });
 in
 {
   options = {
@@ -72,34 +75,38 @@ in
       }
       {
         commands = [
-          { command = "${myplugins}/check_postgres_replication *"; options = [ "NOPASSWD" ]; }
           { command = "${myplugins}/check_last_file_date /backup2/*"; options = [ "NOPASSWD" ]; }
         ];
         users = [ "naemon" ];
+        runAs = "ALL";
+      }
+      {
+        commands = [
+          { command = "${myplugins}/check_postgres_replication *"; options = [ "NOPASSWD" ]; }
+        ];
+        users = [ "naemon" ];
         runAs = "postgres";
       }
       {
         commands = [
           { command = "${myplugins}/check_mysql_replication *"; options = [ "NOPASSWD" ]; }
-          { command = "${myplugins}/check_last_file_date /backup2/*"; options = [ "NOPASSWD" ]; }
         ];
         users = [ "naemon" ];
         runAs = "mysql";
       }
       {
         commands = [
-          { command = "${myplugins}/check_redis_replication *"; options = [ "NOPASSWD" ]; }
-          { command = "${myplugins}/check_last_file_date /backup2/*"; options = [ "NOPASSWD" ]; }
+          { command = "${myplugins}/check_openldap_replication *"; options = [ "NOPASSWD" ]; }
         ];
         users = [ "naemon" ];
-        runAs = "redis";
+        runAs = "openldap";
       }
       {
         commands = [
-          { command = "${myplugins}/check_last_file_date /backup2/*"; options = [ "NOPASSWD" ]; }
+          { command = "${myplugins}/check_redis_replication *"; options = [ "NOPASSWD" ]; }
         ];
         users = [ "naemon" ];
-        runAs = "backup";
+        runAs = "redis";
       }
     ];
     environment.etc."mdadm.conf" = {
index c302e453f08663f74fa26514beb688074e9bc914..2b80eee96f4643fbe836ccdc6aa7b48f917acb91 100644 (file)
@@ -1,4 +1,4 @@
-{ ... }:
+{ config, pkgs, ... }:
 {
   service = [
     {
       use = "local-service";
       check_command = ["check_last_file_date" "/backup2/eldiron/mysql_backup" "7" "mysql"];
     }
+    {
+      service_description = "Openldap replication for eldiron is up to date";
+      use = "local-service";
+      check_command = let
+        name = "eldiron";
+        hcfg = config.myServices.databasesReplication.openldap.hosts.eldiron;
+        base = config.myServices.databasesReplication.openldap.base;
+        eldiron_schemas = pkgs.callPackage ../databases/openldap/eldiron_schemas.nix {};
+        ldapConfig = pkgs.writeText "slapd.conf" ''
+          ${eldiron_schemas}
+          moduleload  back_hdb
+          backend     hdb
+          database    hdb
+
+          suffix    "${hcfg.base}"
+          directory ${base}/${name}/openldap
+          '';
+      in [
+        "check_openldap_replication"
+        hcfg.url
+        hcfg.dn
+        "${config.secrets.location}/openldap_replication/eldiron/replication_password"
+        hcfg.base
+        ldapConfig
+      ];
+    }
+    {
+      service_description = "Last openldap dump in /backup2/eldiron/openldap_backup is not too old";
+      use = "local-service";
+      check_command = ["check_last_file_date" "/backup2/eldiron/openldap_backup" "7" "openldap"];
+    }
   ];
 }
index 1ab9fc3e179d3ced392eaefe714526c1c3486a67..66fb812bf1ba342cccd89614aa0a1324d34935ba 100644 (file)
@@ -76,6 +76,7 @@
     check_ntp = "$USER1$/check_ntp_time -t 30 -q -H 0.arch.pool.ntp.org";
     check_mysql_replication = "${sudo} -u mysql $USER2$/check_mysql_replication \"$ARG1$\" \"$ARG2$\"";
     check_postgresql_replication = "${sudo} -u postgres $USER2$/check_postgres_replication \"$ARG1$\" \"$ARG2$\" \"$ARG3$\"";
+    check_openldap_replication = "${sudo} -u openldap $USER2$/check_openldap_replication \"$ARG1$\" \"$ARG2$\" \"$ARG3$\" \"$ARG4$\" \"$ARG5$\"";
     check_redis_replication = "${sudo} -u redis $USER2$/check_redis_replication \"$ARG1$\"";
     check_mailq = "$USER1$/check_mailq -s -w 1 -c 2";
 
diff --git a/modules/private/monitoring/plugins/check_openldap_replication b/modules/private/monitoring/plugins/check_openldap_replication
new file mode 100755 (executable)
index 0000000..b511ff2
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+STATE_OK=0
+STATE_WARNING=1
+STATE_CRITICAL=2
+STATE_UNKNOWN=3
+
+distant_host="$1"
+replication_dn="$2"
+replication_pw="$3"
+base="$4"
+config="$5"
+
+to_date() {
+  i="$1"
+  i=$(echo "$i" | grep contextCSN | cut -d":" -f2 | sed -e "s/\s//g")
+  i=$(echo "$i" | cut -d"#" -f1)
+  i=$(echo "$i" | cut -d"." -f1)
+  echo "$i"
+}
+
+# ldap
+remote_ldap=$(ldapsearch -H $distant_host -D "$replication_dn" -y "$replication_pw" -b "$base" -s base -LLL contextCSN )
+exit_code_remote=$?
+remote_ldap=$(to_date "$remote_ldap")
+
+# slapcat
+local_ldap=$(slapcat -b "$base" -f "$config" -a "(entryDN=$base)")
+exit_code_local=$?
+local_ldap=$(to_date "$local_ldap")
+
+offset=$(($remote_ldap - $local_ldap))
+
+if [[ $exit_code_remote -ne 0 || $exit_code_local -ne 0 ]]; then
+  echo "UNKNOWN - Impossible to run ldap command"
+  exit $STATE_UNKNOWN
+elif [[ -z "$offset" ]]; then
+  echo "UNKNOWN - No replication found"
+  exit $STATE_UNKNOWN
+else
+  output="Replication lag for openldap is ${offset}s"
+  LC_ALL=C lag=$(printf "%.*f" 0 $lag)
+
+  if [[ $offset -lt 5 ]]; then
+    echo "OK - $output"
+    exit $STATE_OK
+  elif [[ $offset -lt 10 ]]; then
+    echo "WARNING - $output"
+    exit $STATE_WARNING
+  else
+    echo "CRITICAL - $output"
+    exit $STATE_CRITICAL
+  fi
+fi
index 3d51fa3bdaf2305fbf0b9bc4d2edde6060d4ec40..1b7f136c76bca46e89bacb988dfc3ace93fdfa46 100644 (file)
         };
       };
     };
+    openldap = {
+      enable = true;
+      base = "/backup2";
+      hosts = {
+        eldiron = {
+          url = "ldaps://${myconfig.env.ldap.host}:636";
+          dn = myconfig.env.ldap.replication_dn;
+          password = myconfig.env.ldap.replication_pw;
+          base = myconfig.env.ldap.base;
+        };
+      };
+    };
   };
 
   # This value determines the NixOS release with which your system is