1
0
Fork 0

add test for authelia

This commit is contained in:
ibizaman 2023-12-10 21:56:31 -08:00 committed by Pierre Penninckx
parent c467d07359
commit 9a5a10a824
4 changed files with 197 additions and 42 deletions

View file

@ -91,6 +91,7 @@
]);
};
}
// (vm_test "authelia" ./test/vm/authelia.nix)
// (vm_test "ldap" ./test/vm/ldap.nix)
// (vm_test "postgresql" ./test/vm/postgresql.nix)
// (vm_test "monitoring" ./test/vm/monitoring.nix)

View file

@ -6,6 +6,18 @@ let
fqdn = "${cfg.subdomain}.${cfg.domain}";
autheliaCfg = config.services.authelia.instances.${fqdn};
template = file: newPath: replacements:
let
templatePath = newPath + ".template";
sedPatterns = lib.strings.concatStringsSep " " (lib.attrsets.mapAttrsToList (from: to: "\"s|${from}|${to}|\"") replacements);
in
''
ln -fs ${file} ${templatePath}
rm ${newPath} || :
sed ${sedPatterns} ${templatePath} > ${newPath}
'';
in
{
options.shb.authelia = {
@ -46,31 +58,27 @@ in
type = lib.types.submodule {
options = {
jwtSecretFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = "File containing the JWT secret.";
};
ldapAdminPasswordFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = "File containing the LDAP admin user password.";
};
sessionSecretFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = "File containing the session secret.";
};
notifierSMTPPasswordFile = lib.mkOption {
type = lib.types.str;
description = "File containing the STMP password for the notifier.";
};
storageEncryptionKeyFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = "File containing the storage encryption key.";
};
identityProvidersOIDCHMACSecretFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = "File containing the identity provider OIDC HMAC secret.";
};
identityProvidersOIDCIssuerPrivateKeyFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = "File containing the identity provider OIDC issuer private key.";
};
};
@ -83,22 +91,40 @@ in
default = [];
};
smtpHost = lib.mkOption {
type = lib.types.str;
description = "SMTP host.";
example = "smtp.example.com";
};
smtpPort = lib.mkOption {
type = lib.types.int;
description = "SMTP port.";
default = 587;
};
smtpUsername = lib.mkOption {
type = lib.types.str;
description = "SMTP username.";
example = "postmaster@smtp.example.com";
smtp = lib.mkOption {
description = "SMTP options.";
default = null;
type = lib.types.nullOr (lib.types.submodule {
options = {
from_address = lib.mkOption {
type = lib.types.str;
description = "SMTP address from which the emails originate.";
example = "authelia@mydomain.com";
};
from_name = lib.mkOption {
type = lib.types.str;
description = "SMTP name from which the emails originate.";
default = "Authelia";
};
host = lib.mkOption {
type = lib.types.str;
description = "SMTP host to send the emails to.";
};
port = lib.mkOption {
type = lib.types.port;
description = "SMTP port to send the emails to.";
default = 25;
};
username = lib.mkOption {
type = lib.types.str;
description = "Username to connect to the SMTP host.";
};
passwordFile = lib.mkOption {
type = lib.types.str;
description = "File containing the password to connect to the SMTP host.";
};
};
});
};
rules = lib.mkOption {
@ -109,6 +135,13 @@ in
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = builtins.length cfg.oidcClients > 0;
message = "Must have at least one oidc client otherwise Authelia refuses to start.";
}
];
# Overriding the user name so we don't allow any weird characters anywhere. For example, postgres users do not accept the '.'.
users = {
groups.${autheliaCfg.user} = {};
@ -127,14 +160,15 @@ in
};
# See https://www.authelia.com/configuration/methods/secrets/
environmentVariables = {
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = cfg.secrets.ldapAdminPasswordFile;
AUTHELIA_SESSION_SECRET_FILE = cfg.secrets.sessionSecretFile;
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = toString cfg.secrets.ldapAdminPasswordFile;
AUTHELIA_SESSION_SECRET_FILE = toString cfg.secrets.sessionSecretFile;
# Not needed since we use peer auth.
# AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE = "/run/secrets/authelia/postgres_password";
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = cfg.secrets.storageEncryptionKeyFile;
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = cfg.secrets.notifierSMTPPasswordFile;
AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = cfg.secrets.identityProvidersOIDCHMACSecretFile;
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE = cfg.secrets.identityProvidersOIDCIssuerPrivateKeyFile;
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = toString cfg.secrets.storageEncryptionKeyFile;
AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = toString cfg.secrets.identityProvidersOIDCHMACSecretFile;
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE = toString cfg.secrets.identityProvidersOIDCIssuerPrivateKeyFile;
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = lib.mkIf (!(isNull cfg.smtp)) (toString cfg.smtp.passwordFile);
};
settings = {
server.host = "127.0.0.1";
@ -197,12 +231,14 @@ in
};
};
notifier = {
smtp = {
host = cfg.smtpHost;
port = cfg.smtpPort;
username = cfg.smtpUsername;
sender = "Authelia <authelia@${cfg.domain}>";
# identifier = "";
filesystem = lib.mkIf (isNull cfg.smtp) {
filename = "/tmp/authelia-notifications";
};
smtp = lib.mkIf (!(isNull cfg.smtp)) {
host = cfg.smtp.host;
port = cfg.smtp.port;
username = cfg.smtp.username;
sender = "${cfg.smtp.from_name} <${cfg.smtp.from_address}>";
subject = "[Authelia] {title}";
startup_check_address = "test@authelia.com";
};
@ -225,7 +261,6 @@ in
}
] ++ cfg.rules;
};
identity_providers.oidc.clients = cfg.oidcClients;
telemetry = {
metrics = {
enabled = true;
@ -233,12 +268,34 @@ in
};
};
};
settingsFiles = map (client: "/var/lib/authelia-${fqdn}/oidc_client_${client.id}.yaml") cfg.oidcClients;
};
systemd.services."authelia-${fqdn}".preStart =
let
mkCfg = client:
let
secretFile = client.secretFile;
clientWithTmpl = {
identity_providers.oidc.clients = [
((lib.attrsets.filterAttrs (name: v: name != "secretFile") client) // {
secret = "%SECRET%";
})
];
};
tmplFile = pkgs.writeText "oidc_client_${client.id}.yaml" (lib.generators.toYAML {} clientWithTmpl);
in
template tmplFile "/var/lib/authelia-${fqdn}/oidc_client_${client.id}.yaml" {
"%SECRET%" = "$(cat ${toString secretFile})";
};
in
lib.mkBefore (lib.concatStringsSep "\n" (map mkCfg cfg.oidcClients));
services.nginx.virtualHosts.${fqdn} = {
sslCertificate = "/var/lib/acme/${cfg.domain}/cert.pem";
sslCertificateKey = "/var/lib/acme/${cfg.domain}/key.pem";
forceSSL = true;
forceSSL = lib.mkIf config.shb.ssl.enable true;
sslCertificate = lib.mkIf config.shb.ssl.enable "/var/lib/acme/${cfg.domain}/cert.pem";
sslCertificateKey = lib.mkIf config.shb.ssl.enable "/var/lib/acme/${cfg.domain}/key.pem";
# Taken from https://github.com/authelia/authelia/issues/178
# TODO: merge with config from https://matwick.ca/authelia-nginx-sso/
locations."/".extraConfig = ''

69
test/vm/authelia.nix Normal file
View file

@ -0,0 +1,69 @@
{ pkgs, lib, ... }:
let
ldapAdminPassword = "ldapAdminPassword";
in
{
basic = pkgs.nixosTest {
name = "authelia-basic";
nodes.machine = { config, pkgs, ... }: {
imports = [
{
options = {
shb.ssl.enable = lib.mkEnableOption "ssl";
shb.backup = lib.mkOption { type = lib.types.anything; };
};
}
../../modules/blocks/authelia.nix
../../modules/blocks/ldap.nix
../../modules/blocks/postgresql.nix
];
shb.ldap = {
enable = true;
dcdomain = "dc=example,dc=com";
subdomain = "ldap";
domain = "example.com";
ldapUserPasswordFile = pkgs.writeText "user_password" ldapAdminPassword;
jwtSecretFile = pkgs.writeText "jwt_secret" "securejwtsecret";
};
shb.authelia = {
enable = true;
subdomain = "authelia";
domain = "example.com";
ldapEndpoint = "ldap://127.0.0.1:${builtins.toString config.shb.ldap.ldapPort}";
dcdomain = config.shb.ldap.dcdomain;
secrets = {
jwtSecretFile = pkgs.writeText "jwtSecretFile" "jwtSecretFile";
ldapAdminPasswordFile = pkgs.writeText "ldapAdminPasswordFile" ldapAdminPassword;
sessionSecretFile = pkgs.writeText "sessionSecretFile" "sessionSecretFile";
storageEncryptionKeyFile = pkgs.writeText "storageEncryptionKeyFile" "storageEncryptionKeyFile";
identityProvidersOIDCHMACSecretFile = pkgs.writeText "identityProvidersOIDCHMACSecretFile" "identityProvidersOIDCHMACSecretFile";
# This needs to be of the correct shape and at least 2048 bits. Generated with:
# nix run nixpkgs#openssl -- genrsa -out keypair.pem 2048
identityProvidersOIDCIssuerPrivateKeyFile = pkgs.writeText "identityProvidersOIDCIssuerPrivateKeyFile" (builtins.readFile ./keypair.pem);
};
oidcClients = [
{
id = "myclient";
description = "My Client";
secretFile = pkgs.writeText "secret" "mysecuresecret";
public = "false";
authorization_policy = "one_factor";
redirect_uris = [ "https://myclient.exapmle.com/redirect" ];
}
];
};
};
testScript = { nodes, ... }: ''
start_all()
machine.wait_for_unit("lldap.service")
machine.wait_for_unit("authelia-authelia.example.com.service")
'';
};
}

28
test/vm/keypair.pem Normal file
View file

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC2x1rFx98p6djQ
X0mJ8nUMnS3LU7ih8UU5soW/TVhdcioe+NUevLjq0Qe/RXAz+yjhAxmJoWsFwMuy
PKQKDbnqLH6Rf2qPiOvg5NB/vINuVpnAo9mQUJlJOrWKe6/pk6FWD0YxGiwETEIX
bdARazOo/n5emQCZ7XwFy9ULlZkURIt9co/SxhMaD0Q+P1eev0lt01XG5ZLg9wL8
CHIkasqK5huKFUnHVyq8+ApVrzsANsvjFSLwd985FpIF+DYcVQ+8ZmwVrbZTzFFC
Pjee8CrhO1ZxOAPwVm7qNTtZ4es8xJyMJvijk6grqLGcWSIWTMAwxmN7feOuEvvk
RlDf9DmpAgMBAAECggEACP51jySrDLAQ/wznTJpRi+u6loYhwFdD26dXGT8kNWHy
JGjEbPEmrMhZKB5xu18VJ4Bca/c1UdjHNTeybzu2balfl4eEbfhz+fKsd1KmiYIJ
qg7t/GHY7x9sUjqMoRLmhhp1juI9rv71JBu/WLIUnlDalUtUWh6zYwIhE0M634I8
GjN4hCxvbVgQEyY4kMBvCcT9sixwm407qL7LfqlsT8KTGB9UU2cC1HD4B/pUKVzw
x+vN93S6KS2SrjaYhAb1xHgxU6Bl1jT1IH8yAXVlmBBmDL9dNEJtD/kuX8kfbvuC
yFY5NWVapSgyIhURkaHqJKmziaq51K1xHGCZYBDsYQKBgQDq0ovgTNBzgmwyl/ye
ZgUIWc/5tE2LlyoM8XTok9EB+8CnoBek8JFo9DVfNzTv+UCUXb7DCveuS1Jb0JY0
Xi4gOSczVV297Lszziogxuni4ax/1Nezah/WSffVEowakPuTLK+0dst0QxWC6+Db
m4OHJY5qjS/mh3rLhFdjXcmAoQKBgQDHQ0BAg8AhlFz9fTxit1pyHuVs1EcEBjqI
UOS1ClS+BDcjERVBJ8GKiZj2/la37OLlQuguH2AXX//wVC5rZEXP38+ELemW0BZC
JFKaY5PYufMcGVd6JBDYCoEa/JERJsD87ADBAUj/kIMfvka/it9PID9jgMPaVESE
LYIsRv40CQKBgQCtdJ0yMEuCJ4L41GAcOUvaYU1JLDBjvmOnb+xlqFqpVmd26sDM
a49dsZaDIOqPoNRdQ+oXdNCEBMtvWuK5CCCWWOFl/9bg5i9aEx33XDeECiM7weMb
enbN+ZGB6NNpBFNw4X9glKew16TaMpbEYVmEyO8sMeKCLO09zCIpGiwwQQKBgQCF
++dhOfXf3mXkoOgQrJ8pazLzSY1y3ElRTatrPEYc+rKkZqE3DWdrIvhy5DQlOiia
5bE/CiPPs+JhlAkedu8mRqS/iSuvF75PvSK540kPioE4nKWgYE3fJrkHD1rwAHH1
3y7mmFmgVmiE2Kmzs8pR5yoYWwXWcaEci4kjAp19GQKBgQDRpy4ojGUmKdDffcGU
pEpl+dGpC3YuGwEsopDTYJSjANq0p5QGcQo9L140XxBEaFd4k/jwvVh2VRx4KmkC
wyFODOk4vbq1NKljLC9yRo6UbUZuzWBsyjP62OHPR5MBg5FQgd4RI6/c3EpAhFGX
pM/CH7yZXp7Brhp4RcdbwhQnIA==
-----END PRIVATE KEY-----