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}
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
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";
--- /dev/null
+{ 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)
--- /dev/null
+{ 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;
+ };
+}
+
+
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;
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 = {
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 = {
}
{
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" = {
-{ ... }:
+{ 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"];
+ }
];
}
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";
--- /dev/null
+#!/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
};
};
};
+ 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