add test for authelia
This commit is contained in:
parent
c467d07359
commit
9a5a10a824
4 changed files with 197 additions and 42 deletions
|
@ -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)
|
||||
|
|
|
@ -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
69
test/vm/authelia.nix
Normal 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
28
test/vm/keypair.pem
Normal 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-----
|
Loading…
Reference in a new issue