Compare commits

...

2 commits
main ... users2

Author SHA1 Message Date
ibizaman
b26023a4ce home-assistant: actually test ldap login 2026-06-23 16:30:10 +02:00
ibizaman
ff60a64131 test: allow to set login button selector 2026-06-22 20:37:54 +02:00
6 changed files with 138 additions and 18 deletions

View file

@ -4013,6 +4013,9 @@
"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.html#services-home-assistant-options-shb.home-assistant.ldap.enable"
],

View file

@ -139,10 +139,16 @@ in
userGroup = lib.mkOption {
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";
};
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 {
type = lib.types.bool;
description = ''
@ -277,6 +283,7 @@ in
args = [
"http://${cfg.ldap.host}:${toString cfg.ldap.port}"
cfg.ldap.userGroup
cfg.ldap.adminGroup
];
meta = true;
}

View file

@ -127,16 +127,34 @@ shb.home-assistant.ldap
enable = true;
host = "127.0.0.1";
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.
Now, go to the LDAP server at `http://ldap.example.com`,
create the `home-assistant_user` group,
create a user and add it to one or both groups.
When that's done, go back to the Home-Assistant server at
`http://home-assistant.example.com` and login with that user.
This will create a LDAP group declaratively
and add the user `homeAssitantUser` as a user
and the user `homeAssitantAdmin` as an admin.
LDAP users can be added to the groups imperatively too through the LLDAP web UI.
### With SSO Support {#services-home-assistant-usage-sso}

View file

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

View file

@ -295,6 +295,10 @@ in
type = str;
default = "[Ll]ogin";
};
loginButtonSelector = mkOption {
type = str;
default = ''get_by_role("button", name=re.compile('${cfg.loginButtonNameRegex}'))'';
};
loginSpawnsNewPage = mkOption {
type = bool;
default = false;
@ -412,8 +416,8 @@ in
# Assumes we don't need to login, so skip this.
if u['username'] is not None or u['password'] is not None:
print(f"Clicking button {testCfg['loginButtonNameRegex']}")
page.get_by_role("button", name=re.compile(testCfg['loginButtonNameRegex'])).click()
print("Clicking login button")
page.${cfg.loginButtonSelector}.click()
for line in u['nextPageExpect']:
print(f"Running: {line}")
@ -529,11 +533,14 @@ in
ensureUsers = {
alice = {
email = "alice@example.com";
# Display name is required by at least home-assistant.
displayName = "Alice Alice";
groups = [ "user_group" ];
password.result = config.shb.hardcodedsecret.alice.result;
};
bob = {
email = "bob@example.com";
displayName = "Bob Bob";
# Purposely not adding bob to the user_group
# so we can make sure users only part admins
# can also login normally.
@ -542,6 +549,7 @@ in
};
charlie = {
email = "charlie@example.com";
displayName = "Charlie Charlie";
groups = [ "other_group" ];
password.result = config.shb.hardcodedsecret.charlie.result;
};

View file

@ -1,4 +1,9 @@
{ pkgs, shb, ... }:
{
pkgs,
shb,
lib,
...
}:
let
commonTestScript = shb.test.mkScripts {
hasSSL = { node, ... }: !(isNull node.config.shb.home-assistant.ssl);
@ -87,6 +92,9 @@ let
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 = [
{
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 =
{ config, ... }:
{
@ -120,12 +193,13 @@ let
ldap =
{ config, ... }:
{
shb.lldap.debug = lib.mkForce true;
shb.home-assistant = {
ldap = {
enable = true;
host = "127.0.0.1";
port = config.shb.lldap.webUIListenPort;
userGroup = "homeassistant_user";
userGroup = "user_group";
};
};
};
@ -248,6 +322,11 @@ in
ldap = shb.test.runNixOSTest {
name = "homeassistant_ldap";
nodes.client = {
imports = [
clientLdapLogin
];
};
nodes.server = {
imports = [
basic
@ -256,9 +335,14 @@ in
];
};
nodes.client = { };
testScript = commonTestScript.access;
testScript = commonTestScript.access.override {
waitForPorts =
{ node, ... }:
[
8123
node.config.shb.lldap.webUIListenPort
];
};
};
# Not yet supported