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 "ldap" ./test/vm/ldap.nix)
|
||||||
// (vm_test "postgresql" ./test/vm/postgresql.nix)
|
// (vm_test "postgresql" ./test/vm/postgresql.nix)
|
||||||
// (vm_test "monitoring" ./test/vm/monitoring.nix)
|
// (vm_test "monitoring" ./test/vm/monitoring.nix)
|
||||||
|
|
|
@ -6,6 +6,18 @@ let
|
||||||
fqdn = "${cfg.subdomain}.${cfg.domain}";
|
fqdn = "${cfg.subdomain}.${cfg.domain}";
|
||||||
|
|
||||||
autheliaCfg = config.services.authelia.instances.${fqdn};
|
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
|
in
|
||||||
{
|
{
|
||||||
options.shb.authelia = {
|
options.shb.authelia = {
|
||||||
|
@ -46,31 +58,27 @@ in
|
||||||
type = lib.types.submodule {
|
type = lib.types.submodule {
|
||||||
options = {
|
options = {
|
||||||
jwtSecretFile = lib.mkOption {
|
jwtSecretFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.path;
|
||||||
description = "File containing the JWT secret.";
|
description = "File containing the JWT secret.";
|
||||||
};
|
};
|
||||||
ldapAdminPasswordFile = lib.mkOption {
|
ldapAdminPasswordFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.path;
|
||||||
description = "File containing the LDAP admin user password.";
|
description = "File containing the LDAP admin user password.";
|
||||||
};
|
};
|
||||||
sessionSecretFile = lib.mkOption {
|
sessionSecretFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.path;
|
||||||
description = "File containing the session secret.";
|
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 {
|
storageEncryptionKeyFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.path;
|
||||||
description = "File containing the storage encryption key.";
|
description = "File containing the storage encryption key.";
|
||||||
};
|
};
|
||||||
identityProvidersOIDCHMACSecretFile = lib.mkOption {
|
identityProvidersOIDCHMACSecretFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.path;
|
||||||
description = "File containing the identity provider OIDC HMAC secret.";
|
description = "File containing the identity provider OIDC HMAC secret.";
|
||||||
};
|
};
|
||||||
identityProvidersOIDCIssuerPrivateKeyFile = lib.mkOption {
|
identityProvidersOIDCIssuerPrivateKeyFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.path;
|
||||||
description = "File containing the identity provider OIDC issuer private key.";
|
description = "File containing the identity provider OIDC issuer private key.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -83,22 +91,40 @@ in
|
||||||
default = [];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
smtpHost = lib.mkOption {
|
smtp = lib.mkOption {
|
||||||
|
description = "SMTP options.";
|
||||||
|
default = null;
|
||||||
|
type = lib.types.nullOr (lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
from_address = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
description = "SMTP host.";
|
description = "SMTP address from which the emails originate.";
|
||||||
example = "smtp.example.com";
|
example = "authelia@mydomain.com";
|
||||||
};
|
};
|
||||||
|
from_name = lib.mkOption {
|
||||||
smtpPort = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
description = "SMTP port.";
|
|
||||||
default = 587;
|
|
||||||
};
|
|
||||||
|
|
||||||
smtpUsername = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
description = "SMTP username.";
|
description = "SMTP name from which the emails originate.";
|
||||||
example = "postmaster@smtp.example.com";
|
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 {
|
rules = lib.mkOption {
|
||||||
|
@ -109,6 +135,13 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
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 '.'.
|
# Overriding the user name so we don't allow any weird characters anywhere. For example, postgres users do not accept the '.'.
|
||||||
users = {
|
users = {
|
||||||
groups.${autheliaCfg.user} = {};
|
groups.${autheliaCfg.user} = {};
|
||||||
|
@ -127,14 +160,15 @@ in
|
||||||
};
|
};
|
||||||
# See https://www.authelia.com/configuration/methods/secrets/
|
# See https://www.authelia.com/configuration/methods/secrets/
|
||||||
environmentVariables = {
|
environmentVariables = {
|
||||||
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = cfg.secrets.ldapAdminPasswordFile;
|
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = toString cfg.secrets.ldapAdminPasswordFile;
|
||||||
AUTHELIA_SESSION_SECRET_FILE = cfg.secrets.sessionSecretFile;
|
AUTHELIA_SESSION_SECRET_FILE = toString cfg.secrets.sessionSecretFile;
|
||||||
# Not needed since we use peer auth.
|
# Not needed since we use peer auth.
|
||||||
# AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE = "/run/secrets/authelia/postgres_password";
|
# AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE = "/run/secrets/authelia/postgres_password";
|
||||||
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = cfg.secrets.storageEncryptionKeyFile;
|
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = toString cfg.secrets.storageEncryptionKeyFile;
|
||||||
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = cfg.secrets.notifierSMTPPasswordFile;
|
AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = toString cfg.secrets.identityProvidersOIDCHMACSecretFile;
|
||||||
AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = cfg.secrets.identityProvidersOIDCHMACSecretFile;
|
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE = toString cfg.secrets.identityProvidersOIDCIssuerPrivateKeyFile;
|
||||||
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE = cfg.secrets.identityProvidersOIDCIssuerPrivateKeyFile;
|
|
||||||
|
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = lib.mkIf (!(isNull cfg.smtp)) (toString cfg.smtp.passwordFile);
|
||||||
};
|
};
|
||||||
settings = {
|
settings = {
|
||||||
server.host = "127.0.0.1";
|
server.host = "127.0.0.1";
|
||||||
|
@ -197,12 +231,14 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
notifier = {
|
notifier = {
|
||||||
smtp = {
|
filesystem = lib.mkIf (isNull cfg.smtp) {
|
||||||
host = cfg.smtpHost;
|
filename = "/tmp/authelia-notifications";
|
||||||
port = cfg.smtpPort;
|
};
|
||||||
username = cfg.smtpUsername;
|
smtp = lib.mkIf (!(isNull cfg.smtp)) {
|
||||||
sender = "Authelia <authelia@${cfg.domain}>";
|
host = cfg.smtp.host;
|
||||||
# identifier = "";
|
port = cfg.smtp.port;
|
||||||
|
username = cfg.smtp.username;
|
||||||
|
sender = "${cfg.smtp.from_name} <${cfg.smtp.from_address}>";
|
||||||
subject = "[Authelia] {title}";
|
subject = "[Authelia] {title}";
|
||||||
startup_check_address = "test@authelia.com";
|
startup_check_address = "test@authelia.com";
|
||||||
};
|
};
|
||||||
|
@ -225,7 +261,6 @@ in
|
||||||
}
|
}
|
||||||
] ++ cfg.rules;
|
] ++ cfg.rules;
|
||||||
};
|
};
|
||||||
identity_providers.oidc.clients = cfg.oidcClients;
|
|
||||||
telemetry = {
|
telemetry = {
|
||||||
metrics = {
|
metrics = {
|
||||||
enabled = true;
|
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} = {
|
services.nginx.virtualHosts.${fqdn} = {
|
||||||
sslCertificate = "/var/lib/acme/${cfg.domain}/cert.pem";
|
forceSSL = lib.mkIf config.shb.ssl.enable true;
|
||||||
sslCertificateKey = "/var/lib/acme/${cfg.domain}/key.pem";
|
sslCertificate = lib.mkIf config.shb.ssl.enable "/var/lib/acme/${cfg.domain}/cert.pem";
|
||||||
forceSSL = true;
|
sslCertificateKey = lib.mkIf config.shb.ssl.enable "/var/lib/acme/${cfg.domain}/key.pem";
|
||||||
# Taken from https://github.com/authelia/authelia/issues/178
|
# Taken from https://github.com/authelia/authelia/issues/178
|
||||||
# TODO: merge with config from https://matwick.ca/authelia-nginx-sso/
|
# TODO: merge with config from https://matwick.ca/authelia-nginx-sso/
|
||||||
locations."/".extraConfig = ''
|
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