diff --git a/configuration.nix b/configuration.nix index 033e208..9d0d35d 100644 --- a/configuration.nix +++ b/configuration.nix @@ -38,8 +38,13 @@ let ipv4 = "10.9.1.1"; }; }; - + hostname = "customs"; openvpn-auth = import ./openvpn-auth { inherit pkgs; }; + secrets-path = "/etc/nixos/secrets/"; + update_authorized_keys = pkgs.writeShellScriptBin "update_authorized_keys" '' + ${pkgs.python3.withPackages (pp: [ pp.ldap3 ])}/bin/python ${./update_authorized_keys.py} ${hostname} ${secrets-path}/ldap-password.txt + ''; + in { imports = [ @@ -77,7 +82,7 @@ in { options = [ "rw" "mode=755" "size=200M" "nosuid" "nodev" "relatime" "noexec" ]; }; - networking.hostName = "customs"; + networking.hostName = hostname; networking.useDHCP = false; networking.vlans = { laser = { @@ -92,8 +97,8 @@ in { script = '' ${pkgs.coreutils}/bin/install --owner=root --mode=700 --directory /mnt/secrets/nginx/ ${pkgs.coreutils}/bin/install --owner=root --mode=400 -t /mnt/secrets/nginx/ \ - /etc/nixos/secrets/nginx/at.hackerspace.pl.key \ - /etc/nixos/secrets/nginx/at.hackerspace.pl.crt + ${secrets-path}/nginx/at.hackerspace.pl.key \ + ${secrets-path}/nginx/at.hackerspace.pl.crt ${pkgs.acl}/bin/setfacl -m "u:nginx:rx" /mnt/secrets/nginx ${pkgs.acl}/bin/setfacl -m "u:nginx:r" /mnt/secrets/nginx/* ''; @@ -351,6 +356,7 @@ in { enable = true; systemCronJobs = [ "*/5 * * * * root ${log-neigh}" + "0 3 * * * root ${update_authorized_keys}" ]; }; @@ -472,10 +478,10 @@ in { proto udp6 dev vpn dev-type tun - ca /etc/nixos/secrets/openvpn-public/ca.crt - cert /etc/nixos/secrets/openvpn-public/server.crt - key /etc/nixos/secrets/openvpn-public/server.key - dh /etc/nixos/secrets/openvpn-public/dh.pem + ca ${secrets-path}/openvpn-public/ca.crt + cert ${secrets-path}/openvpn-public/server.crt + key ${secrets-path}/openvpn-public/server.key + dh ${secrets-path}/openvpn-public/dh.pem server 10.9.1.0 255.255.255.0 push "route 10.0.0.0 255.0.0.0" @@ -493,7 +499,7 @@ in { environment.systemPackages = with pkgs; [ vim tcpdump htop nmon tmux git file procps parted dmidecode ack utillinux nmap mosh ncdu tree lz4 bind - rxvt_unicode.terminfo + rxvt_unicode.terminfo update_authorized_keys ]; programs.mtr.enable = true; diff --git a/update_authorized_keys.py b/update_authorized_keys.py new file mode 100755 index 0000000..2b336f2 --- /dev/null +++ b/update_authorized_keys.py @@ -0,0 +1,82 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i python3 -p python3Packages.ldap3 + +from ldap3 import Server, Connection, LEVEL +from ldap3.utils.dn import escape_rdn +import getpass +import logging +from pathlib import Path +import filecmp +import os + +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("hostname", help="hostname") +parser.add_argument("ldap_pass_file", type=Path, help="file containing lap password") + +header_warning = """ +################################### WARNING #################################### +# This file was created automatically from LDAP database and *WILL* be +# overwritten. If you need to add / remove keys make changes to +# {}-admin group / members sshPublicKey attributes in LDAP and rerun +# update_authorized_keys script +################################################################################ +""".lstrip() + +def get_keys(connection: Connection, group: str): + c = connection + + c.search( + search_base="ou=People,dc=hackerspace,dc=pl", + search_filter=( + "(&" + "(objectClass=hsMember)" + f"(memberOf=cn={escape_rdn(group)},ou=Group,dc=hackerspace,dc=pl)" + ")" + ), + search_scope=LEVEL, + attributes=["sshPublicKey"], + ) + + admin_keys = [] + for entry in c.response: + attributes = entry["attributes"] + for key in entry["attributes"]["sshPublicKey"]: + yield key.strip() + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + args = parser.parse_args() + + user = f"cn={escape_rdn(args.hostname)},ou=Boxen,dc=hackerspace,dc=pl" + password = args.ldap_pass_file.read_text().strip() + + s = Server("ldap.hackerspace.pl", use_ssl=True) + with Connection(s, user=user, password=password, raise_exceptions=True) as c: + keys = list(get_keys(c, f"{args.hostname}-admin")) + if len(keys) < 2: + raise Exception("Less then two keys found - aborting") + + ssh_dir = Path("/", "root", ".ssh") + ssh_dir.mkdir(mode=700, exist_ok=True) + ssh_dir.chmod(0o700) + new_file = ssh_dir.joinpath("authorized_keys_new") + old_file = ssh_dir.joinpath("authorized_keys") + try: + new_file.unlink() + except FileNotFoundError: + pass + new_file.write_bytes( + header_warning.format(args.hostname).encode() + b"\n".join(keys) + ) + if not old_file.exists(): + logging.info('Creating new "authorized_keys" file') + os.rename(new_file, old_file) + elif filecmp.cmp(new_file, old_file, shallow=False): + logging.info('Nothing changed - "authorized_keys" file is up to date') + new_file.unlink() + else: + logging.info('Keys changed - overwriting "authorized_keys" file') + os.rename(new_file, old_file)