forked from DGNum/infrastructure
feat(radius): Init config
This commit is contained in:
parent
3e763f419a
commit
f173138848
14 changed files with 426 additions and 0 deletions
62
machines/compute01/k-radius/default.nix
Normal file
62
machines/compute01/k-radius/default.nix
Normal file
|
@ -0,0 +1,62 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./module.nix ];
|
||||
|
||||
services.k-radius = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
# URL to the Kanidm server
|
||||
uri = "https://sso.dgnum.eu";
|
||||
|
||||
# verify the hostname of the Kanidm server
|
||||
verify_hostnames = "true";
|
||||
|
||||
# Strict CA verification
|
||||
verify_ca = "false";
|
||||
verify_certificate = "false";
|
||||
|
||||
# Path to the kanidm ca
|
||||
|
||||
# Default vlans for groups that don't specify one.
|
||||
radius_default_vlan = 99;
|
||||
|
||||
# A list of Kanidm groups which must be a member
|
||||
# before they can authenticate via RADIUS.
|
||||
radius_required_groups = [ "radius_access@sso.dgnum.eu" ];
|
||||
|
||||
# A mapping between Kanidm groups and VLANS
|
||||
radius_groups = [
|
||||
{
|
||||
spn = "dgnum_members@idm.example.com";
|
||||
vlan = 1;
|
||||
}
|
||||
{
|
||||
spn = "dgnum_clients@idm.example.com";
|
||||
vlan = 2;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
authTokenFile = config.age.secrets."radius-auth_token_file".path;
|
||||
privateKeyPasswordFile =
|
||||
config.age.secrets."radius-private_key_password_file".path;
|
||||
|
||||
certs = builtins.listToAttrs (builtins.map (name:
|
||||
lib.nameValuePair name
|
||||
config.age.secrets."radius-${name}_pem_file".path) [
|
||||
"ca"
|
||||
"cert"
|
||||
"dh"
|
||||
"key"
|
||||
]);
|
||||
|
||||
radiusClients = { };
|
||||
};
|
||||
|
||||
dgn-secrets.matches."^radius-.*$" = { owner = "radius"; };
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 1812 ];
|
||||
networking.firewall.allowedUDPPorts = [ 1812 ];
|
||||
}
|
181
machines/compute01/k-radius/module.nix
Normal file
181
machines/compute01/k-radius/module.nix
Normal file
|
@ -0,0 +1,181 @@
|
|||
{ config, lib, pkgs, sources, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkEnableOption mkIf mkOption types;
|
||||
|
||||
settingsFormat = pkgs.formats.toml { };
|
||||
|
||||
python3 = (import sources.nixos-python { }).python311;
|
||||
|
||||
pykanidm = pkgs.callPackage ./packages/pykanidm.nix { inherit python3; };
|
||||
rlm_python =
|
||||
pkgs.callPackage ./packages/rlm_python.nix { inherit python3 pykanidm; };
|
||||
|
||||
cfg = config.services.k-radius;
|
||||
in {
|
||||
options.services.k-radius = {
|
||||
enable = mkEnableOption "a freeradius service linked to kanidm.";
|
||||
|
||||
settings = mkOption { inherit (settingsFormat) type; };
|
||||
|
||||
freeradius = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.freeradius.overrideAttrs (old: {
|
||||
buildInputs = (old.buildInputs or [ ])
|
||||
++ [ (pkgs.python3.withPackages (ps: [ ps.kanidm ])) ];
|
||||
});
|
||||
};
|
||||
|
||||
configDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/radius/raddb";
|
||||
description =
|
||||
"The path of the freeradius server configuration directory.";
|
||||
};
|
||||
|
||||
authTokenFile = mkOption {
|
||||
type = types.path;
|
||||
description = "File to the auth token for the service account.";
|
||||
};
|
||||
|
||||
radiusClients = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
secret = mkOption { type = types.path; };
|
||||
ipaddr = mkOption { type = types.str; };
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = "A mapping of clients and their authentication tokens.";
|
||||
};
|
||||
|
||||
certs = {
|
||||
ca = mkOption {
|
||||
type = types.str;
|
||||
description = "The signing CA of the RADIUS certificate.";
|
||||
};
|
||||
dh = mkOption {
|
||||
type = types.str;
|
||||
description =
|
||||
"The output of `openssl dhparam -in ca.pem -out dh.pem 2048`.";
|
||||
};
|
||||
cert = mkOption {
|
||||
type = types.str;
|
||||
description = "The certificate for the RADIUS server.";
|
||||
};
|
||||
key = mkOption {
|
||||
type = types.str;
|
||||
description = "The signing key for the RADIUS certificate.";
|
||||
};
|
||||
};
|
||||
|
||||
privateKeyPasswordFile = mkOption { type = types.path; };
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users = {
|
||||
users.radius = {
|
||||
group = "radius";
|
||||
description = "Radius daemon user";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
groups.radius = { };
|
||||
};
|
||||
|
||||
services.k-radius.settings = {
|
||||
ca_path = cfg.certs.ca;
|
||||
|
||||
radius_cert_path = cfg.certs.cert;
|
||||
radius_key_path = cfg.certs.key;
|
||||
radius_dh_path = cfg.certs.dh;
|
||||
radius_ca_path = cfg.certs.ca;
|
||||
};
|
||||
|
||||
systemd.services.radius = {
|
||||
description = "FreeRadius server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
wants = [ "network.target" ];
|
||||
|
||||
preStart = ''
|
||||
cp -R ${cfg.freeradius}/etc/raddb/* ${cfg.configDir}
|
||||
cp -R ${rlm_python}/etc/raddb/* ${cfg.configDir}
|
||||
|
||||
chmod -R u+w ${cfg.configDir}
|
||||
|
||||
# disable auth via methods kanidm doesn't support
|
||||
rm ${cfg.configDir}/mods-available/sql
|
||||
rm ${cfg.configDir}/mods-enabled/{passwd,totp}
|
||||
|
||||
# enable the python and cache modules
|
||||
ln -nsf ${cfg.configDir}/mods-available/python3 ${cfg.configDir}/mods-enabled/python3
|
||||
ln -nsf ${cfg.configDir}/sites-available/check-eap-tls ${cfg.configDir}/sites-enabled/check-eap-tls
|
||||
|
||||
# write the clients configuration
|
||||
rm ${cfg.configDir}/clients.conf && touch ${cfg.configDir}/clients.conf
|
||||
${builtins.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs
|
||||
(name:
|
||||
{ secret, ipaddr }: ''
|
||||
cat <<EOF >> ${cfg.configDir}/client.conf
|
||||
client ${name} {
|
||||
ipaddr = ${ipaddr}
|
||||
secret = $(cat "${secret}")
|
||||
proto = *
|
||||
}
|
||||
EOF
|
||||
'') cfg.radiusClients))}
|
||||
|
||||
# Copy the kanidm configuration
|
||||
cat <<EOF > /var/lib/radius/kanidm.toml
|
||||
auth_token = "$(cat "${cfg.authTokenFile}")"
|
||||
EOF
|
||||
|
||||
cat ${
|
||||
settingsFormat.generate "kanidm.toml" cfg.settings
|
||||
} >> /var/lib/radius/kanidm.toml
|
||||
chmod u+w /var/lib/radius/kanidm.toml
|
||||
|
||||
# Copy the certificates to the correct directory
|
||||
rm -rf ${cfg.configDir}/certs && mkdir -p ${cfg.configDir}/certs
|
||||
|
||||
cp ${cfg.certs.ca} ${cfg.configDir}/certs/ca.pem
|
||||
|
||||
${pkgs.openssl}/bin/openssl rehash ${cfg.configDir}/certs
|
||||
|
||||
cp ${cfg.certs.dh} ${cfg.configDir}/certs/dh.pem
|
||||
|
||||
cat ${cfg.certs.cert} ${cfg.certs.key} > ${cfg.configDir}/certs/server.pem
|
||||
|
||||
# Write the password of the private_key in the eap module
|
||||
sed -i ${cfg.configDir}/mods-available/eap \
|
||||
-e "s/whatever/$(cat "${cfg.privateKeyPasswordFile}")/"
|
||||
|
||||
# Check the configuration
|
||||
# ${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
|
||||
'';
|
||||
|
||||
path = [ pkgs.openssl pkgs.gnused ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
"${cfg.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout";
|
||||
ExecReload = [
|
||||
"${cfg.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
|
||||
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
|
||||
];
|
||||
User = "radius";
|
||||
Group = "radius";
|
||||
DynamicUser = true;
|
||||
Restart = "on-failure";
|
||||
RestartSec = 2;
|
||||
LogsDirectory = "radius";
|
||||
StateDirectory = "radius";
|
||||
Environment = [
|
||||
"KANIDM_RLM_CONFIG=/var/lib/radius/kanidm.toml"
|
||||
"PYTHONPATH=${rlm_python.pythonPath}"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
34
machines/compute01/k-radius/packages/pykanidm.nix
Normal file
34
machines/compute01/k-radius/packages/pykanidm.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{ lib, fetchFromGitHub, python3 }:
|
||||
|
||||
let
|
||||
pname = "kanidm";
|
||||
version = "0.0.3";
|
||||
in python3.pkgs.buildPythonPackage {
|
||||
inherit pname version;
|
||||
format = "pyproject";
|
||||
|
||||
disabled = python3.pythonOlder "3.8";
|
||||
|
||||
src = (fetchFromGitHub {
|
||||
owner = pname;
|
||||
repo = pname;
|
||||
# Latest 1.1.0-rc.15 tip
|
||||
rev = "a5ca8018e3a636dbb0a79b3fd869db059d92979d";
|
||||
hash = "sha256-PFGoeGn7a/lVR6rOmOKA3ydAoo3/+9RlkwBAKS22Psg=";
|
||||
}) + "/pykanidm";
|
||||
|
||||
nativeBuildInputs = with python3.pkgs; [ poetry-core ];
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [ aiohttp pydantic toml (authlib.overridePythonAttrs (_: { doCheck = false; })) ];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
pythonImportsCheck = [ "kanidm" ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Kanidm client library";
|
||||
homepage = "https://github.com/kanidm/kanidm/tree/master/pykanidm";
|
||||
license = licenses.mpl20;
|
||||
maintainers = with maintainers; [ arianvp hexa ];
|
||||
};
|
||||
}
|
13
machines/compute01/k-radius/packages/python_path.patch
Normal file
13
machines/compute01/k-radius/packages/python_path.patch
Normal file
|
@ -0,0 +1,13 @@
|
|||
diff --git a/rlm_python/mods-available/python3 b/rlm_python/mods-available/python3
|
||||
index 978536f8a..90c71fca0 100644
|
||||
--- a/rlm_python/mods-available/python3
|
||||
+++ b/rlm_python/mods-available/python3
|
||||
@@ -13,7 +13,7 @@ python3 {
|
||||
# item is GLOBAL TO THE SERVER. That is, you cannot have two
|
||||
# instances of the python module, each with a different path.
|
||||
#
|
||||
- python_path="/usr/lib64/python3.8:/usr/lib/python3.8:/usr/lib/python3.8/site-packages:/usr/lib64/python3.8/site-packages:/usr/lib64/python3.8/lib-dynload:/usr/local/lib/python3.8/site-packages:/etc/raddb/mods-config/python3/"
|
||||
+ python_path="@kanidm_python@:/etc/raddb/mods-config/python3/"
|
||||
|
||||
module = "kanidm.radius"
|
||||
# python_path = ${modconfdir}/${.:name}
|
33
machines/compute01/k-radius/packages/rlm_python.nix
Normal file
33
machines/compute01/k-radius/packages/rlm_python.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{ stdenv, fetchFromGitHub, python3, pykanidm }:
|
||||
|
||||
let pythonPath = with python3.pkgs; makePythonPath [ pykanidm ];
|
||||
|
||||
in stdenv.mkDerivation rec {
|
||||
pname = "rlm_python";
|
||||
version = "1.1.0-rc.15";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "kanidm";
|
||||
repo = "kanidm";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-0y8juXS61Z9zxOdsWAQ6lJurP+n855Nela6egYRecok=";
|
||||
};
|
||||
|
||||
patches = [ ./python_path.patch ];
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace rlm_python/mods-available/python3 \
|
||||
--replace "@kanidm_python@" "${pythonPath}"
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/etc/raddb/
|
||||
cp -R rlm_python/{mods-available,sites-available} $out/etc/raddb/
|
||||
'';
|
||||
|
||||
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
|
||||
|
||||
passthru = { inherit pythonPath; };
|
||||
|
||||
preferLocalBuild = true;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue