automatic update of authorized_keys from LDAP
parent
eb7734033d
commit
a82c44f3cc
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue