infrastructure/machines/nixos/compute01/satosa/module.nix
Tom Hubrecht 88d9b8c3e3
Some checks failed
Check meta / check_dns (pull_request) Successful in 19s
Check meta / check_meta (pull_request) Successful in 20s
Check workflows / check_workflows (pull_request) Successful in 24s
Build all the nodes / ap01 (pull_request) Successful in 1m15s
Build all the nodes / bridge01 (pull_request) Successful in 1m53s
Build all the nodes / geo01 (pull_request) Successful in 1m55s
Build all the nodes / geo02 (pull_request) Successful in 1m53s
Build all the nodes / compute01 (pull_request) Successful in 2m33s
Build all the nodes / rescue01 (pull_request) Successful in 2m13s
Build all the nodes / storage01 (pull_request) Successful in 1m57s
Run pre-commit on all files / check (pull_request) Successful in 30s
Build all the nodes / web02 (pull_request) Successful in 1m47s
Build all the nodes / vault01 (pull_request) Successful in 2m21s
Build all the nodes / web03 (pull_request) Successful in 1m40s
Build all the nodes / web01 (pull_request) Successful in 2m54s
Check meta / check_dns (push) Successful in 20s
Check meta / check_meta (push) Successful in 19s
Check workflows / check_workflows (push) Successful in 25s
Build all the nodes / ap01 (push) Successful in 1m16s
Build all the nodes / bridge01 (push) Successful in 1m41s
Build all the nodes / geo02 (push) Successful in 1m44s
Build all the nodes / geo01 (push) Successful in 1m53s
Build all the nodes / compute01 (push) Successful in 2m20s
Build all the nodes / rescue01 (push) Successful in 1m49s
Build all the nodes / storage01 (push) Successful in 1m46s
Build all the nodes / vault01 (push) Successful in 1m45s
Run pre-commit on all files / check (push) Successful in 30s
Build all the nodes / web02 (push) Has been cancelled
Build all the nodes / web01 (push) Has been cancelled
Build all the nodes / web03 (push) Has been cancelled
chore: Add license and copyright information
Signed-off-by: Tom Hubrecht <tom.hubrecht@dgnum.eu>
Acked-by: Ryan Lahfa <ryan.lahfa@dgnum.eu>
Acked-by: Maurice Debray <maurice.debray@dgnum.eu>
Acked-by: Lubin Bailly <lubin.bailly@dgnum.eu>
Acked-by: Jean-Marc Gailis <jean-marc.gailis@dgnum.eu> as the legal authority, at the time of writing, in DGNum.
Acked-by: Elias Coppens <elias.coppens@dgnum.eu> as a member, at the time of writing, of the DGNum executive counsel.
2024-12-13 12:41:38 +01:00

204 lines
5 KiB
Nix

# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
mkDefault
mkEnableOption
mkIf
mkOption
types
;
yamlFormat = pkgs.formats.yaml { };
configFile = yamlFormat.generate "proxy_conf.yaml" cfg.proxyConf;
cfg = config.services.satosa;
mkYamlFiles =
files: builtins.attrValues (builtins.mapAttrs (name: yamlFormat.generate "${name}.yaml") files);
pyEnv = cfg.package.python.withPackages (ps: [
cfg.package
ps.gunicorn
]);
in
{
options.services.satosa = {
enable = mkEnableOption "SATOSA, a SAML and OIDC proxy.";
package = mkOption {
type = types.package;
default = import ./package { inherit pkgs; };
};
port = mkOption {
type = types.port;
default = 8080;
};
host = mkOption { type = types.str; };
workers = mkOption {
type = types.int;
default = 1;
};
configureNginx = mkOption {
type = types.bool;
default = true;
};
proxyConf = mkOption {
inherit (yamlFormat) type;
default = { };
};
envFile = mkOption {
type = with types; nullOr path;
default = null;
};
internalAttributes = mkOption {
inherit (yamlFormat) type;
default = { };
};
frontendModules = mkOption {
type = types.attrsOf yamlFormat.type;
default = { };
};
backendModules = mkOption {
type = types.attrsOf yamlFormat.type;
default = { };
};
microServices = mkOption {
type = types.attrsOf yamlFormat.type;
default = { };
};
};
config = mkIf cfg.enable {
services.satosa.proxyConf = builtins.mapAttrs (_: mkDefault) {
BASE = "https://${cfg.host}";
COOKIE_STATE_NAME = "satosa_state";
COOKIE_SECURE = true;
COOKIE_HTTPONLY = true;
COOKIE_SAMESITE = "None";
COOKIE_MAX_AGE = "1200";
CONTEXT_STATE_DELETE = true;
INTERNAL_ATTRIBUTES = yamlFormat.generate "internal_attributes.yaml" {
attributes = cfg.internalAttributes;
};
BACKEND_MODULES = mkYamlFiles cfg.backendModules;
FRONTEND_MODULES = mkYamlFiles cfg.frontendModules;
MICRO_SERVICES = mkYamlFiles cfg.microServices;
LOGGING = {
version = 1;
formatters.simple.format = "[%(asctime)s] [%(levelname)s] [%(name)s.%(funcName)s] %(message)s";
handlers.stdout = {
class = "logging.StreamHandler";
stream = "ext://sys.stdout";
level = "DEBUG";
formatter = "simple";
};
loggers = {
satosa.level = "DEBUG";
saml2.level = "DEBUG";
oidcendpoint.level = "DEBUG";
pyop.level = "DEBUG";
oic.level = "DEBUG";
root = {
level = "DEBUG";
handlers = [ "stdout" ];
};
};
};
};
systemd.services = {
satosa-metadata = {
script = ''
umask 077
# Generate a secret key/certificate if none are present
mkdir -p ssl
if [ ! -f "ssl/.created" ]; then
${pkgs.openssl}/bin/openssl req -x509 \
-newkey rsa:2048 \
-keyout ssl/key.pem \
-out ssl/cert.pem \
-sha256 \
-days 3650 \
-nodes \
-subj "/C=FR/ST=Île de France/L=Paris/O=DGNum/OU=./CN=saml-idp.dgnum.eu" \
&& touch ssl/.created
fi
mkdir -p metadata
${cfg.package}/bin/satosa-saml-metadata \
--dir metadata \
--sign ${configFile} ssl/key.pem ssl/cert.pem
'';
serviceConfig = {
Type = "oneshot";
User = "satosa";
Group = "satosa";
DynamicUser = true;
StateDirectory = "satosa";
WorkingDirectory = "/var/lib/satosa";
EnvironmentFile = lib.optional (cfg.envFile != null) cfg.envFile;
};
};
satosa = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
wants = [ "satosa-metadata.service" ];
serviceConfig = {
User = "satosa";
Group = "satosa";
DynamicUser = true;
Type = "notify";
RuntimeDirectory = "satosa";
StateDirectory = "satosa";
WorkingDirectory = cfg.package;
ExecStart = ''
${pyEnv}/bin/gunicorn \
-w ${builtins.toString cfg.workers} \
-b 127.0.0.1:${builtins.toString cfg.port} \
--pythonpath ${pyEnv}/${pkgs.python3.sitePackages} \
satosa.wsgi:app
'';
ExecReload = "${pkgs.util-linux}/bin/kill -s HUP $MAINPID";
KillMode = "mixed";
TimeoutStopSec = "5";
EnvironmentFile = lib.optional (cfg.envFile != null) cfg.envFile;
};
environment = {
SATOSA_CONFIG = configFile;
};
};
};
users.users.satosa = {
isSystemUser = true;
group = "satosa";
home = "/var/lib/satosa";
};
users.groups.satosa = { };
};
}