2 Commits

  1. 2
      machines/manager/default.nix
  2. 6
      machines/manager/secrets/ldap-sync.conf
  3. 20
      machines/manager/users.nix
  4. 4
      machines/node/users.nix
  5. 23
      packages/usermgr/default.nix
  6. 12
      packages/usermgr/pyproject.toml
  7. 83
      packages/usermgr/usermgr.py
  8. 1
      shared/default.nix
  9. 80
      shared/userenv.nix

2
machines/manager/default.nix

@ -1,5 +1,5 @@
_:
{ lib, config, ... }:
{ pkgs, lib, config, ... }:
with lib;

6
machines/manager/secrets/ldap-sync.conf

@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:P/MCZdzK9TmH9UYNj0+FrA71cRTGylDNxbvY2z21RaCm5m3adh5laQWcGQMPA7dv7TLkniIOb5FOW/7bPwRlmnul/h1sjML6DnpnxDeKAt8jJaGtNJ6G7VkClObGxfaDvBJ2j8EEzjPIdIAISc7QTSOc91gN0U7TF3xZUkDwlxvsL1IK0oqvcSOf8HPB5TxmToe6tns8Ctaugl2h8N0yo4NTK4kFtE1BO8XT4n17KLJAsaIkbg5Rox3AgPOBIdOhbajpWWgpJEbIa38gO66V4ep93Iy7yrJHVt2jJ/bH31wQouxn/FFitLnxqe4naJjrw6XP2auLgEPfM95B7rsRrDH/HYW1hXsJklVc349qZm593eI3SnkDcUow1RxE6eIqXqU1mdBWIiE7RCyxdSgXwtQ2AZu3n+5m+V5wGHTBOuJPbOxX91LmXcX0pyzxrYigZNNUDCJTY02uQuyr8x8XFrYOvr3UuAfCFrWNQTcKYo7QlwgkPvKekYRMklkQ6f6pPwoyrNotSboSz0tThwVKP7c0XUlT4Yi9sEe50b4C6CAz1iw4UI/Z2UFz022H/gV4qx2BAIDKyFaFxSjEB7zZ4B42PIRLx/D7MFx1ie436TCqicYowQFg/ZGVZLvcE+iChAtI1Kl6h45eYI59XCqgfYce5KAAiwHdCkHqlkR66JPQc3Bu4xOsas8e441mQ1HGuHOmEwNbkXum/S4gDT+YFQkjrASuzFsxAVOFsj1gtXhoWscP47c+YszVH7iCCt/iXNZFFaITjWAk8mSnVLkshbeqEYpE57UsVDlv3gjPbwXARTAIDr1//puMGOhUM5JvLcxExq8q67A9+DSr+eKVZLCFxqjxyWvwf/Zx5WwiH1LuWMdMHPXDENoE49zlZHfiia6p3RWTvgPtP7ag/J0fyUKhF/SHmFExeAB1gcnrWaMKCUxfBpwM6rs58oAEgk+Sd4YXPgHjM6QEA4I9OJ2g8yoSIUVu8mkLFZhpId46tRPE5Wup5zd4dvKUCe51rD511pT5GtpYsRex+7VQLbVYDm0hgEVrKPnvgANWnHDdI7sW/sfNfC3k9MtMhIDpWZxO4fB/CMkfbJxt8s+pxI3ukzYMfpOo0Kj/Olmj2sotePwmcD8ARSBmlaeKojcay6jFpE1zVJw2iaJNENk=,iv:Mkq9T1fe9r18E4cumOxoG/u8MZ6Jv1Ee7P5ynJ2uTLo=,tag:/VHv16mSinntACDZALgA/g==,type:str]",
"data": "ENC[AES256_GCM,data:N2iJKT62rRhA0uW9+bGzLVg+cwnF6FB9Wnn02MAeFlw2BNKF5zo8kTCE6t5QiyXRafCIWRWFyBR12js2WeD8WPX2wIRpeGNeZboQRN/PBtRA5OohAbyOqCerDbqRpbUnxAF7qpi+DYHyfofITm09FryS2qh/q2a7FMfwRt7HzJlxKsYk/viFvkTelBq8nbx32V1g0sEAflG41DpzYyffDymR4CLwWmw5i8H3UQEhfhVP/9VAHf74r9D/4lxspiQZJ01b2gJkJ+MOWZgE6QSfY0ILMIRquLpjrE++mt4NXZY5sp6ZzsFyI83rwGE4aMrvL3uWZDrUp02hWHegm3kZ5BJQuYdIV2YHprh/0N17az6kQrvbVpTu2WScyt8nyFEYtISX8AVsGHql7JtOaBsmkViq9oS7aExYPGg+b6ef6qhEMAYDJWVA/dxTRSLOaUnC0sYg5Q9kRvdjtxtdf5hmnES7QdvZMihSLwF7EssEF/WpPj8vHbRr8C/FpDBrki1xlbQRliNTk0RlQ0w+LfjU9n0xSGaRq3VEF+Gat/KtxQSGi6B80i/6PR6XM86DDQR15eBO2PPrinzvFAccgm7F4/T9kWAfN9hJSSCBSCupn2d87xAn2PyuqCgLfi6wBES80EjXe8BTExFeMfUN0qxzp9XVDPuChIieSk69oQ/YRHmVgG23M+YQ1GHrtAcoYCNDH6eYD7ao3oJFYsaUPrRR86HbcVeFqpjiQa0iDLn5/0K4WZeMgVPA8Hramkbx/rgGAESAAOfFpB1PTkdHva34MVqQM6RGF97ANKA/4r+/YuOtEr5AyrAhYoJUAHI+nZCv8epVFj3XNDAUq3tkd7a1hbbcSRcczt/diQsQBz8f1ori+jGyDIXhaAKktOYs046sEpy3YULcpkhiztFsL9+Ps7UOpH+VfS2QeA8WRmBiNiUzLMykP4hZgGZNP35sQ8j13V4pyAuoCl85zDUHmjkpWLJsfrl431JJVNjoB2hCiloLFqbjYrnXoUoytYPJs1KU1tl+dQGcWOQWaRou8QIVGVu2mbW0Tdi9xStJ+mOVqXbdawRspGZkUAlemmz0HxGI+susvlpS+VsqPfNHj7X5WGrZVaZYpYy6O4UfcYPtkeqfLTfvIUVuch9BC5FIyA8dwMr9N7/aWPP+bJupMIRO,iv:7JGYvq0NGtUeBJbSYM47j520h87BwghfvRZX4AvFmhM=,tag:ghKC0C7yOfe5ePkNLOIaKA==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
@ -15,8 +15,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHOUsrS2tyTUVEUEZaN3pR\nR0drZ3JDdUtMRHhJaGtONWtwK2Ftc1JsUFRJCjZtYXFubmlpTWtHNVpRU1ZhdThl\nUFVXUERDazdvSGtDOXc1VFNqeTRKRGcKLS0tIDhTdWhWU0dCUUYrZkdSRkVxbGFE\nYkg2Nk42VnUwZFhZVXdsWHFKYnUrMVEK0Aj6aON/QIFT2fsv2D9Ajvu+f6mHT4Q3\nm5uo99snnGEl3VIcvhC2yKGEtw3XOVpCfk5xHYLV2nlSs4WCc2DrkA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2023-08-24T13:12:16Z",
"mac": "ENC[AES256_GCM,data:1zIxWiMGyS25X4C+Her3aJS2c3NdCunX0GyOTdGScavzbgv10ndjrkGPk/uuvTGY2DquGUxdQFu4Pot8zsAM3c5mCnl1ebTWLNQaS8futgllbGJG+EnOr7gUzg518GhmuKm87AN/HdcU0rTNPn3vDx3bTzo7znecSdi0v/6tOPI=,iv:rnyg7+YWN9VrJzli8hdNnQshl/qC80n5Ya3gYB8Yshs=,tag:u5aE64fUhuLuvWXk0ZF4vA==,type:str]",
"lastmodified": "2023-09-10T09:39:37Z",
"mac": "ENC[AES256_GCM,data:IE/GHU+0Mlt5hSOUxF9cGe0kMweuPJ3A8I9C6ZZUMeGPT3XLiaWarlVNw3JwnwQ3cn6U4gHc3UdpVM3Ia5W1Qozm0LB/KhMVfBRNXAWWhYqt33Z6V9rcchtUrb94ET/98mRCeqDbJk8UvniXeSj4edWILZM4xEslccbnncx01GU=,iv:3YiShgapFLiAhBgHsVUyKNrBvvme+WL0Z1xziRLjGkg=,tag:uFbWy1XNrpWACdJjZE9rcQ==,type:str]",
"pgp": [
{
"created_at": "2023-06-26T09:22:36Z",

20
machines/manager/users.nix

@ -3,13 +3,17 @@
with lib;
{
programs.ssh = {
package = pkgs.openssh.overrideAttrs (final: prev: {
patches = prev.patches ++ [
../../patches/openssh-keysign-check-remove.patch
];
});
nixpkgs.overlays = [
(self: super: {
openssh = super.openssh.overrideAttrs (final: prev: {
patches = prev.patches ++ [
../../patches/openssh-keysign-check-remove.patch
];
});
})
];
programs.ssh = {
extraConfig = ''
EnableSSHKeysign yes
@ -24,4 +28,8 @@ with lib;
owner = "root";
group = "root";
};
users.users."root".packages = [
(pkgs.callPackage ../../packages/usermgr { })
];
}

4
machines/node/users.nix

@ -16,7 +16,9 @@ with lib;
};
services.openssh = {
#logLevel = "DEBUG3";
settings = {
#LogLevel = "DEBUG3";
};
extraConfig = ''
IgnoreRhosts no

23
packages/usermgr/default.nix

@ -0,0 +1,23 @@
{ python3Packages
, ...
}:
with python3Packages;
buildPythonApplication {
pname = "usermgr";
version = "0.1";
format = "pyproject";
nativeBuildInputs = [
setuptools
];
propagatedBuildInputs = [
click
ldap3
];
src = ./.;
}

12
packages/usermgr/pyproject.toml

@ -0,0 +1,12 @@
[project]
name = "usermgr"
version = "0.1"
requires-python = ">=3.9"
dependencies = [
"click>=8",
"ldap3>=2.9"
]
[project.scripts]
usermgr = "usermgr:cli"

83
packages/usermgr/usermgr.py

@ -0,0 +1,83 @@
import click
import ssl
from ldap3 import Server, Connection, Tls
@click.group()
@click.option('--server', default='edir1.rz.hs-fulda.de', help='LDAP server URL')
@click.option('--username', prompt=True, default='cn=fdhpc,ou=AI,o=FH-Fulda', help='LDAP bind username')
@click.option('--password', prompt=True, hide_input=True, help='LDAP bind password')
@click.pass_context
def cli(ctx, server, username, password):
tls = Tls(validate=ssl.CERT_REQUIRED,
version=ssl.PROTOCOL_TLSv1_2,
ciphers="AES256-GCM-SHA384")
server = Server(server, tls=tls, get_info="ALL")
ctx.obj = Connection(server,
username,
password,
auto_bind=True)
@cli.command()
@click.pass_context
def list(ctx):
ctx.obj.search('o=FH-Fulda', '''(&
(cn=fd*)
(objectClass=inetOrgPerson)
(groupMembership=cn=ORG-AI-HPC,ou=AI,o=FH-Fulda)
(!
(|
(description=*funktion*)
(loginDisabled=true)
(sn=fd*)
)
)
)''',
attributes = ['cn', 'member', 'sn', 'givenName'])
for e in ctx.obj.entries:
click.echo(f'{click.style(e.cn, fg="blue", bold=True)}: {e.sn}, {e.givenName}')
def find(ctx, name):
from ldap3.utils.conv import escape_filter_chars
ctx.obj.search('o=FH-Fulda', f'''(&
(cn={escape_filter_chars(name)})
(objectClass=inetOrgPerson)
(!
(|
(description=*funktion*)
(loginDisabled=true)
(sn=fd*)
)
)
)''')
if not ctx.obj.entries:
ctx.fail(f'No user found: {name}')
return ctx.obj.entries[0].entry_dn
@cli.command()
@click.argument('name', nargs=-1, required=True)
@click.pass_context
def add(ctx, name):
members = [find(ctx, name) for name in name]
ctx.obj.extend.novell.add_members_to_groups(members, 'cn=ORG-AI-HPC,ou=AI,o=FH-Fulda')
@cli.command()
@click.pass_context
@click.argument('name', nargs=-1, required=True)
def remove(ctx, name):
members = [find(ctx, name) for name in name]
ctx.obj.extend.novell.remove_members_from_groups(members, 'cn=ORG-AI-HPC,ou=AI,o=FH-Fulda')
if __name__ == '__main__':
cli()

1
shared/default.nix

@ -39,6 +39,7 @@
htop
iotop
iftop
file
];
nix.nixPath = [

80
shared/userenv.nix

@ -1,51 +1,73 @@
{ pkgs, lib, ... }:
# This is the environment that we show for the users.
# Hear me out... I already regrett doing this while writing this, but (l)users
# are not willing to pick up the nix-struggle for the greater benefit. So, here
# I am building this shit that I know will fall apart soon.
{ pkgs, lib, config, ... }:
with lib;
let
userenv = pkgs.buildFHSUserEnv {
userenv = pkgs.buildEnv {
name = "userenv";
targetPkgs = pkgs: with pkgs; [
git
postgresql
postgresql.lib
papi
gcc
gdb
gnumake
valgrind
paths = with pkgs; [
autoconf
automake
perl
zlib
python3
libtool
bash
coreutils
curl
fd
flex
pandoc
gcc
gdb
git
gnumake
hwloc
munge
numactl
libbfd
libiberty
libtool
munge
nano
numactl
openmpi
openssh
pandoc
papi
perl
pkgconfig
postgresql
postgresql.lib
python3
ripgrep
tmux
ucx
openmpi
valgrind
vim
nano
wget
curl
tmux
fd
ripgrep
bash
zlib
];
ignoreCollisions = false;
inherit (config.environment) pathsToLink extraOutputsToInstall;
};
in
{
environment.systemPackages = [ userenv ];
# environment.systemPackages = [ userenv ];
# Install userenv to a well-known path
system.systemBuilderCommands = ''
ln -s ${userenv}/bin/userenv $out/userenv
environment.extraInit = ''
if [[ "$(id -gn)" -eq "cluster" ]]; then
export PKG_CONFIG_PATH="${makeSearchPath "lib/pkgconfig" config.environment.profiles}"
fi
'';
environment.profiles = [
"/etc/profiles/per-group/$(id -gn)"
];
environment.etc."userenv" = {
target = "profiles/per-group/cluster";
source = userenv;
};
}
Loading…
Cancel
Save