home-assistant: actually test ldap login

This commit is contained in:
ibizaman 2026-06-22 20:37:32 +02:00
parent ff60a64131
commit b26023a4ce
6 changed files with 132 additions and 16 deletions

View file

@ -4013,6 +4013,9 @@
"services-home-assistant-options-shb.home-assistant.ldap": [ "services-home-assistant-options-shb.home-assistant.ldap": [
"services-home-assistant.html#services-home-assistant-options-shb.home-assistant.ldap" "services-home-assistant.html#services-home-assistant-options-shb.home-assistant.ldap"
], ],
"services-home-assistant-options-shb.home-assistant.ldap.adminGroup": [
"services-home-assistant.html#services-home-assistant-options-shb.home-assistant.ldap.adminGroup"
],
"services-home-assistant-options-shb.home-assistant.ldap.enable": [ "services-home-assistant-options-shb.home-assistant.ldap.enable": [
"services-home-assistant.html#services-home-assistant-options-shb.home-assistant.ldap.enable" "services-home-assistant.html#services-home-assistant-options-shb.home-assistant.ldap.enable"
], ],

View file

@ -139,10 +139,16 @@ in
userGroup = lib.mkOption { userGroup = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "Group users must belong to to be able to login to Nextcloud."; description = "Group users must belong to to be able to login as a user.";
default = "homeassistant_user"; default = "homeassistant_user";
}; };
adminGroup = lib.mkOption {
type = lib.types.str;
description = "Group users must belong to to be able to login as an admin.";
default = "homeassistant_admin";
};
keepDefaultAuth = lib.mkOption { keepDefaultAuth = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
description = '' description = ''
@ -277,6 +283,7 @@ in
args = [ args = [
"http://${cfg.ldap.host}:${toString cfg.ldap.port}" "http://${cfg.ldap.host}:${toString cfg.ldap.port}"
cfg.ldap.userGroup cfg.ldap.userGroup
cfg.ldap.adminGroup
]; ];
meta = true; meta = true;
} }

View file

@ -127,16 +127,34 @@ shb.home-assistant.ldap
enable = true; enable = true;
host = "127.0.0.1"; host = "127.0.0.1";
port = config.shb.lldap.webUIListenPort; port = config.shb.lldap.webUIListenPort;
userGroup = "homeassistant_user";
# This is the default:
# userGroup = "homeassistant_user";
# adminGroup = "homeassistant_admin";
};
shb.lldap.ensureGroups = {
${config.shb.home-assistant.ldap.userGroup} = { };
${config.shb.home-assistant.ldap.adminGroup} = { };
};
shb.lldap.ensureUsers.homeAssistantAdmin = {
groups = [
config.shb.home-assistant.ldap.adminGroup
];
};
shb.lldap.ensureUsers.homeAssistantUser = {
groups = [
config.shb.home-assistant.ldap.userGroup
];
}; };
``` ```
And that's it. This will create a LDAP group declaratively
Now, go to the LDAP server at `http://ldap.example.com`, and add the user `homeAssitantUser` as a user
create the `home-assistant_user` group, and the user `homeAssitantAdmin` as an admin.
create a user and add it to one or both groups. LDAP users can be added to the groups imperatively too through the LLDAP web UI.
When that's done, go back to the Home-Assistant server at
`http://home-assistant.example.com` and login with that user.
### With SSO Support {#services-home-assistant-usage-sso} ### With SSO Support {#services-home-assistant-usage-sso}

View file

@ -7,10 +7,10 @@ stdenvNoCC.mkDerivation {
name = "lldap-ha-auth"; name = "lldap-ha-auth";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "lldap"; owner = "ibizaman";
repo = "lldap"; repo = "lldap";
rev = "7d1f5abc137821c500de99c94f7579761fc949d8"; rev = "adaf17c70336ec2562d23d1b9775579d62691b51";
sha256 = "sha256-8D+7ww70Ja6Qwdfa+7MpjAAHewtCWNf/tuTAExoUrg0="; sha256 = "sha256-4FqfglEss5MlnxvjP40zbxqtwvB/GGMs7HwK9CBNBUQ=";
}; };
nativeBuildInputs = [ nativeBuildInputs = [

View file

@ -533,11 +533,14 @@ in
ensureUsers = { ensureUsers = {
alice = { alice = {
email = "alice@example.com"; email = "alice@example.com";
# Display name is required by at least home-assistant.
displayName = "Alice Alice";
groups = [ "user_group" ]; groups = [ "user_group" ];
password.result = config.shb.hardcodedsecret.alice.result; password.result = config.shb.hardcodedsecret.alice.result;
}; };
bob = { bob = {
email = "bob@example.com"; email = "bob@example.com";
displayName = "Bob Bob";
# Purposely not adding bob to the user_group # Purposely not adding bob to the user_group
# so we can make sure users only part admins # so we can make sure users only part admins
# can also login normally. # can also login normally.
@ -546,6 +549,7 @@ in
}; };
charlie = { charlie = {
email = "charlie@example.com"; email = "charlie@example.com";
displayName = "Charlie Charlie";
groups = [ "other_group" ]; groups = [ "other_group" ];
password.result = config.shb.hardcodedsecret.charlie.result; password.result = config.shb.hardcodedsecret.charlie.result;
}; };

View file

@ -1,4 +1,9 @@
{ pkgs, shb, ... }: {
pkgs,
shb,
lib,
...
}:
let let
commonTestScript = shb.test.mkScripts { commonTestScript = shb.test.mkScripts {
hasSSL = { node, ... }: !(isNull node.config.shb.home-assistant.ssl); hasSSL = { node, ... }: !(isNull node.config.shb.home-assistant.ssl);
@ -87,6 +92,9 @@ let
test.login = { test.login = {
startUrl = "http://${config.test.fqdn}"; startUrl = "http://${config.test.fqdn}";
usernameFieldSelector = ''get_by_role("textbox", name="Username")'';
passwordFieldSelector = ''get_by_role("textbox", name="Password")'';
loginButtonSelector = ''get_by_role("button", name="Log in")'';
testLoginWith = [ testLoginWith = [
{ {
nextPageExpect = [ nextPageExpect = [
@ -109,6 +117,71 @@ let
}; };
}; };
clientLdapLogin =
{ config, ... }:
{
imports = [
shb.test.baseModule
shb.test.clientLoginModule
];
config = {
virtualisation.memorySize = 4096;
test = {
subdomain = "ha";
};
test.login = {
startUrl = "http://${config.test.fqdn}";
usernameFieldSelector = ''get_by_role("textbox", name="Username")'';
passwordFieldSelector = ''get_by_role("textbox", name="Password")'';
loginButtonSelector = ''get_by_role("button", name="Log in")'';
testLoginWith = [
{
username = "alice";
password = "AlicePassword";
nextPageExpect = [
"expect(page.get_by_text('All set!')).to_be_visible(timeout=30000)"
"page.get_by_role('button', name=re.compile('Finish')).click()"
"expect(page).to_have_title(re.compile('Overview'), timeout=15000)"
];
}
{
username = "alice";
password = "notAlicePassword";
nextPageExpect = [
"expect(page.get_by_text('Invalid!')).to_be_visible()"
];
}
{
username = "bob";
password = "BobPassword";
nextPageExpect = [
"expect(page.get_by_text('All set!')).to_be_visible(timeout=30000)"
"page.get_by_role('button', name=re.compile('Finish')).click()"
"expect(page).to_have_title(re.compile('Overview'), timeout=15000)"
];
}
{
username = "bob";
password = "notBobPassword";
nextPageExpect = [
"expect(page.get_by_text('Invalid!')).to_be_visible()"
];
}
{
username = "charlie";
password = "CharliePassword";
nextPageExpect = [
"expect(page.get_by_text('Invalid!')).to_be_visible()"
];
}
];
};
};
};
https = https =
{ config, ... }: { config, ... }:
{ {
@ -120,12 +193,13 @@ let
ldap = ldap =
{ config, ... }: { config, ... }:
{ {
shb.lldap.debug = lib.mkForce true;
shb.home-assistant = { shb.home-assistant = {
ldap = { ldap = {
enable = true; enable = true;
host = "127.0.0.1"; host = "127.0.0.1";
port = config.shb.lldap.webUIListenPort; port = config.shb.lldap.webUIListenPort;
userGroup = "homeassistant_user"; userGroup = "user_group";
}; };
}; };
}; };
@ -248,6 +322,11 @@ in
ldap = shb.test.runNixOSTest { ldap = shb.test.runNixOSTest {
name = "homeassistant_ldap"; name = "homeassistant_ldap";
nodes.client = {
imports = [
clientLdapLogin
];
};
nodes.server = { nodes.server = {
imports = [ imports = [
basic basic
@ -256,9 +335,14 @@ in
]; ];
}; };
nodes.client = { }; testScript = commonTestScript.access.override {
waitForPorts =
testScript = commonTestScript.access; { node, ... }:
[
8123
node.config.shb.lldap.webUIListenPort
];
};
}; };
# Not yet supported # Not yet supported