authentik ldap working; home-assistant auth with LDAP working

This commit is contained in:
Ellis Rahhal 2024-04-25 23:49:16 -07:00
parent 1a2597de28
commit 29877e469d
6 changed files with 317 additions and 206 deletions

View file

@ -1,6 +1,14 @@
TODOS
=====
* HA Authentication
* Use local network authentication, then use Authentik proxy auth in front
* LDAP auth is annoying, and presents a different auth page
* Look into auto-initialization for HA: https://github.com/home-assistant/core/issues/16554
* Using auth_manager API to create user, or edit .storage/auth directly / deploy it
* Authentik
* Auto LDAP deploy
* https://docs.goauthentik.io/docs/providers/ldap/generic_setup
* setup VLANs
* https://wiki.nftables.org/wiki-nftables/index.php/Main_Page
* https://serverfault.com/questions/858556/transparent-firewall-with-nftables-and-vlans

View file

@ -1,5 +1,9 @@
{ config, ... }:
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
openldap
];
services.authentik = {
enable = true;
# Deployed SOPS file
@ -18,8 +22,16 @@
};
};
# HTTP port
networking.firewall.allowedTCPPorts = [ 9000 ];
services.authentik-ldap = {
enable = true;
# Deployed SOPS file
environmentFile = "/run/secrets/authentik/authentik-ldap-env";
};
networking.firewall.allowedTCPPorts = [
# 3389 # LDAP
9000 # Web GUI
];
sops.secrets = {
"authentik/authentik-env" = {
@ -31,6 +43,15 @@
path = "/run/secrets/authentik/authentik-env";
restartUnits = [ "authentik.service" ];
};
"authentik/authentik-ldap-env" = {
format = "yaml";
# @TODO: Move secrets to this folder
sopsFile = ../secrets/authentik.yaml;
owner = "homefree";
path = "/run/secrets/authentik/authentik-ldap-env";
restartUnits = [ "authentik-ldap.service" ];
};
"authentik/postgres-password" = {
format = "yaml";
# @TODO: Move secrets to this folder

View file

@ -12,6 +12,11 @@ in
#-----------------------------------------------------------------------------------------------------
imports = [
# On first run, this has to be commented out, and a single user created.
# Afterward, it can be re-included
## @TODO: Auto-initializatin for HA
## See: https://github.com/home-assistant/core/issues/16554
./ldap.nix
./weather.nix
];
@ -47,7 +52,7 @@ in
"script ui" = "!include scripts.yaml";
"group manual" = groups;
"group ui" = "!include groups.yaml";
# "group ui" = "!include groups.yaml";
http = {
use_x_forwarded_for = true;
@ -112,18 +117,18 @@ in
}
];
media_player = [
{
platform = "yamaha";
host = "10.0.0.41";
source_names = {
HDMI1 = "PC HDMI";
};
zone_names = {
Main_Zone = "Family Room";
};
}
];
# media_player = [
# {
# platform = "yamaha";
# host = "10.0.0.41";
# source_names = {
# HDMI1 = "PC HDMI";
# };
# zone_names = {
# Main_Zone = "Family Room";
# };
# }
# ];
sensor = [
# See: https://github.com/home-assistant/core/issues/64839
@ -151,193 +156,193 @@ in
};
};
}
{
platform = "hp_ilo";
host = "10.0.0.9";
username = "Administrator";
# @TODO: REMOVE
password = "CHANGEME";
monitored_variables = [
{
name = "CPU fanspeed";
sensor_type = "server_health";
unit_of_measurement = "%";
value_template = "{{ ilo_data.fans[\"Fan 1\"].speed[0] }}";
}
{
name = "Fan 2";
sensor_type = "server_health";
unit_of_measurement = "%";
value_template = "{{ ilo_data.fans[\"Fan 2\"].speed[0] }}";
}
{
name = "Fan 3";
sensor_type = "server_health";
unit_of_measurement = "%";
value_template = "{{ ilo_data.fans[\"Fan 3\"].speed[0] }}";
}
{
name = "Server Health";
sensor_type = "server_health";
value_template = "{{ ilo_data.health_at_a_glance }}";
}
{
name = "Server Power Readings (raw)";
sensor_type = "server_power_readings";
}
{
name = "Server Power Status (raw)";
sensor_type = "server_power_status";
}
{
name = "Server health (raw)";
sensor_type = "server_health";
}
{
name = "Inlet temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"01-Inlet Ambient\"].currentreading[0] }}";
}
{
name = "Inlet temperature (raw)";
sensor_type = "server_health";
value_template = "{{ ilo_data.temperature[\"01-Inlet Ambient\"] }}";
}
{
name = "CPU 1 temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"02-CPU 1\"].currentreading[0] }}";
}
{
name = "P1 DIMM 1-4 temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"03-P1 DIMM 1-4\"].currentreading[0] }}";
}
{
name = "HD Max temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"04-HD Max\"].currentreading[0] }}";
}
{
name = "Chipset temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"05-Chipset\"].currentreading[0] }}";
}
{
name = "VR P1 temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"07-VR P1\"].currentreading[0] }}";
}
{
name = "SuperCAP Max temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"08-Supercap Max\"].currentreading[0] }}";
}
{
name = "iLO Zone temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"09-iLO Zone\"].currentreading[0] }}";
}
{
name = "LOM Zon temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"11-LOM Zone\"].currentreading[0] }}";
}
{
name = "PCI 2 temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"13-PCI 2\"].currentreading[0] }}";
}
{
name = "PCI 1 Zone temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"14-PCI 1 Zone\"].currentreading[0] }}";
}
{
name = "PCI 2 Zone temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\15-PCI 2 Zone\].currentreading[0] }}";
}
{
name = "System Board temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"16-System Board\"].currentreading[0] }}";
}
{
name = "Sys Exhaust temperature";
sensor_type = "server_health";
unit_of_measurement = "°C";
value_template = "{{ ilo_data.temperature[\"17-Sys Exhaust\"].currentreading[0] }}";
}
];
}
{
# This includes the config necessary for a washer and dryer.
# Code for dishwasher and mini-washer may be commented out as-needed,
# and are presented only for reference purposes.
# NOTE: YOUR ENTITY NAMES MAY BE DIFFERENT, THEN THIS WON'T WORK WITHOUT TWEAKING
# =================================================================================
# If your washer doesn't have entities named sensor.washer, sensor.washer_run_state
# (and similar for dryer), you have to change the names throughout here!
# NOTE: THIS CODE EXPECTS YOUR THINQ INTEGRATION TO RETURN ENGLISH STRINGS
# =================================================================================
# if your LG account is in another region/language, this will probably break unless
# you take the time to change out state strings like "Standby". Do this by watching
# your machine's entities change states during a run, or look at its history.
platform = "template";
sensors = {
front_load_washer_door_lock = {
friendly_name = "Washer Door Lock";
value_template = "{{ state_attr('sensor.front_load_washer','door_lock') }}";
};
front_load_washer_time_display = {
friendly_name = "Washer Time Display";
value_template = ''
{% if is_state('sensor.front_load_washer_run_state', '-') %}
{% elif is_state('sensor.front_load_washer_run_state', 'unavailable') %}
{% elif is_state('sensor.front_load_washer_run_state', 'Standby') %}
-:--
{% else %}
{{ state_attr("sensor.front_load_washer","remain_time").split(":")[:-1] | join(':') }}
{% endif %}
'';
};
dryer_time_display = {
friendly_name = "Dryer Time Display";
value_template = ''
{% if is_state('sensor.dryer_run_state', '-') %}
{% elif is_state('sensor.dryer_run_state', 'unavailable') %}
{% elif is_state('sensor.dryer_run_state', 'Standby') %}
-:--
{% else %}
{{ state_attr("sensor.dryer","remain_time").split(":")[:-1] | join(':') }}
{% endif %}
'';
};
blank = {
friendly_name = "Blank Sensor";
value_template = "";
};
};
}
# {
# platform = "hp_ilo";
# host = "10.0.0.9";
# username = "Administrator";
# # @TODO: REMOVE
# password = "CHANGEME";
# monitored_variables = [
# {
# name = "CPU fanspeed";
# sensor_type = "server_health";
# unit_of_measurement = "%";
# value_template = "{{ ilo_data.fans[\"Fan 1\"].speed[0] }}";
# }
# {
# name = "Fan 2";
# sensor_type = "server_health";
# unit_of_measurement = "%";
# value_template = "{{ ilo_data.fans[\"Fan 2\"].speed[0] }}";
# }
# {
# name = "Fan 3";
# sensor_type = "server_health";
# unit_of_measurement = "%";
# value_template = "{{ ilo_data.fans[\"Fan 3\"].speed[0] }}";
# }
# {
# name = "Server Health";
# sensor_type = "server_health";
# value_template = "{{ ilo_data.health_at_a_glance }}";
# }
# {
# name = "Server Power Readings (raw)";
# sensor_type = "server_power_readings";
# }
# {
# name = "Server Power Status (raw)";
# sensor_type = "server_power_status";
# }
# {
# name = "Server health (raw)";
# sensor_type = "server_health";
# }
# {
# name = "Inlet temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"01-Inlet Ambient\"].currentreading[0] }}";
# }
# {
# name = "Inlet temperature (raw)";
# sensor_type = "server_health";
# value_template = "{{ ilo_data.temperature[\"01-Inlet Ambient\"] }}";
# }
# {
# name = "CPU 1 temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"02-CPU 1\"].currentreading[0] }}";
# }
# {
# name = "P1 DIMM 1-4 temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"03-P1 DIMM 1-4\"].currentreading[0] }}";
# }
# {
# name = "HD Max temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"04-HD Max\"].currentreading[0] }}";
# }
# {
# name = "Chipset temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"05-Chipset\"].currentreading[0] }}";
# }
# {
# name = "VR P1 temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"07-VR P1\"].currentreading[0] }}";
# }
# {
# name = "SuperCAP Max temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"08-Supercap Max\"].currentreading[0] }}";
# }
# {
# name = "iLO Zone temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"09-iLO Zone\"].currentreading[0] }}";
# }
# {
# name = "LOM Zon temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"11-LOM Zone\"].currentreading[0] }}";
# }
# {
# name = "PCI 2 temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"13-PCI 2\"].currentreading[0] }}";
# }
# {
# name = "PCI 1 Zone temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"14-PCI 1 Zone\"].currentreading[0] }}";
# }
# {
# name = "PCI 2 Zone temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"15-PCI 2 Zone\"].currentreading[0] }}";
# }
# {
# name = "System Board temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"16-System Board\"].currentreading[0] }}";
# }
# {
# name = "Sys Exhaust temperature";
# sensor_type = "server_health";
# unit_of_measurement = "°C";
# value_template = "{{ ilo_data.temperature[\"17-Sys Exhaust\"].currentreading[0] }}";
# }
# ];
# }
# {
# # This includes the config necessary for a washer and dryer.
# # Code for dishwasher and mini-washer may be commented out as-needed,
# # and are presented only for reference purposes.
#
# # NOTE: YOUR ENTITY NAMES MAY BE DIFFERENT, THEN THIS WON'T WORK WITHOUT TWEAKING
# # =================================================================================
# # If your washer doesn't have entities named sensor.washer, sensor.washer_run_state
# # (and similar for dryer), you have to change the names throughout here!
#
# # NOTE: THIS CODE EXPECTS YOUR THINQ INTEGRATION TO RETURN ENGLISH STRINGS
# # =================================================================================
# # if your LG account is in another region/language, this will probably break unless
# # you take the time to change out state strings like "Standby". Do this by watching
# # your machine's entities change states during a run, or look at its history.
#
# platform = "template";
# sensors = {
# front_load_washer_door_lock = {
# friendly_name = "Washer Door Lock";
# value_template = "{{ state_attr('sensor.front_load_washer','door_lock') }}";
# };
# front_load_washer_time_display = {
# friendly_name = "Washer Time Display";
# value_template = ''
# {% if is_state('sensor.front_load_washer_run_state', '-') %}
# {% elif is_state('sensor.front_load_washer_run_state', 'unavailable') %}
# {% elif is_state('sensor.front_load_washer_run_state', 'Standby') %}
# -:--
# {% else %}
# {{ state_attr("sensor.front_load_washer","remain_time").split(":")[:-1] | join(':') }}
# {% endif %}
# '';
# };
#
# dryer_time_display = {
# friendly_name = "Dryer Time Display";
# value_template = ''
# {% if is_state('sensor.dryer_run_state', '-') %}
# {% elif is_state('sensor.dryer_run_state', 'unavailable') %}
# {% elif is_state('sensor.dryer_run_state', 'Standby') %}
# -:--
# {% else %}
# {{ state_attr("sensor.dryer","remain_time").split(":")[:-1] | join(':') }}
# {% endif %}
# '';
# };
#
# blank = {
# friendly_name = "Blank Sensor";
# value_template = "";
# };
# };
# }
];
};
};

View file

@ -0,0 +1,63 @@
{
stdenv,
fetchFromGitHub,
makeWrapper,
openldap,
coreutils,
gnused,
gnugrep,
lib,
}:
stdenv.mkDerivation {
name = "ldap-auth-sh";
src = fetchFromGitHub {
owner = "efficiosoft";
repo = "ldap-auth-sh";
rev = "93b2c00413942908139e37c7432a12bcb705ac87";
sha256 = "1pymp6ki353aqkigr89g7hg5x1mny68m31c3inxf1zr26n5s2kz8";
};
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir -p $out/etc
cat > $out/etc/home-assistant.cfg << 'EOF'
CLIENT="ldapsearch"
SERVER="ldap://localhost:3389"
USERDN="cn=$(ldap_dn_escape "$username"),ou=users,dc=ldap,dc=goauthentik,dc=io"
PW=$password
BASEDN="dc=ldap,dc=goauthentik,dc=io"
SCOPE="subtree"
FILTER="(&(objectClass=user)(sAMAccountName=$(ldap_dn_escape "$username")))"
# USERNAME_PATTERN='^[a-z|A-Z|0-9|_|-|.|@]+$'
on_auth_success() {
# print the meta entries for use in HA
if echo "$output" | grep -qE '^(dn|DN):: '; then
# ldapsearch base64 encodes non-ascii
output=$(echo "$output" | sed -n -e "s/^\(dn\|DN\)\s*::\s*\(.*\)$/\2/p" | base64 -d)
else
output=$(echo "$output" | sed -n -e "s/^\(dn\|DN\)\s*:\s*\(.*\)$/\2/p")
fi
name=$(echo "$output" | sed -nr 's/^cn=([^,]+).*/\1/Ip')
[ -z "$name" ] || echo "name=$name"
}
on_auth_failure() {
echo "$output"
}
EOF
install -D -m755 ldap-auth.sh $out/bin/ldap-auth.sh
wrapProgram $out/bin/ldap-auth.sh \
--prefix PATH : ${
lib.makeBinPath [
openldap
coreutils
gnused
gnugrep
]
} \
--add-flags "$out/etc/home-assistant.cfg"
'';
}

View file

@ -0,0 +1,13 @@
{ pkgs, ... }:
let
ldap-auth-sh = pkgs.callPackage ./ldap-auth-sh.nix;
in
{
services.home-assistant.config.homeassistant.auth_providers = [
{
type = "command_line";
command = "${ldap-auth-sh}/bin/ldap-auth.sh";
meta = true;
}
];
}

View file

@ -1,14 +1,15 @@
authentik:
postgres-password: ENC[AES256_GCM,data:HezgfCXKIiZcvJmoda4=,iv:umWPgOPwcQtnCFKHRKgyjKhhOLZgYfA4VEjyv/mxv2Q=,tag:mkAquT40K4bta9wq1lfUig==,type:str]
authentik-env: ENC[AES256_GCM,data:GC0euKHPIU4cALcr6ZVOY3UqrTz8BdW7fwN0XJXlMYBtRVSpoNd+b8JLx5ZEzvVSNm3JQGwz9PusJPcqLGY01Zx2pIEj+/Gc4rLiUIdAGvTVROGYcpDLkC9TG5iNLGZFbG7bcvOEjcJ8BhJ8MTqhmQOI+l0kvFymq7gAByqqvIxAWFeIQI1ye7metJhTBsKQoYrZHDGgTeNnVkl6S1Ab6JQTuU4DoGDHNpPzKJs4djOvrlv6VKYt9hUkad+JrB7RrLOpV8zY+1Jui/6lBpS9mCaX3PuhK1NQ1QVM5OEM6WrUHW4NvPR2cc0M6PUwq1bIyen6B0+sqXwh3wcmgvlxWlAuBPXDNl04ucm1i+YtT1GRDQMj3RJfAEi9Onxl2tYro1VmkAul+i6mjiehn4csT4bP0tck9HaQC0HemZDW4NirJsyNJjG8DOXO+mCD/zOKav6AIgCvg3wO6POl2S3bP/hFK0xugO+AOo7T9OdF8n2uBCFWuvVqdI0TmqlU5I2n1XR+tTzS4kdX6v9aDuItZf/M/L2u,iv:r/i9Dx+kUOTQ6PIkWBW0ug15R+/SNhrMIJPL0uYWvuo=,tag:g8AJjZ/5T3voBZcszwXLtA==,type:str]
authentik-env: ENC[AES256_GCM,data:h4c0qEj0dK71GeBEoHhG2G9w+3hnEvayhqcpyjXrxa8uaTLtw2+4YgU1DpQIR+PtzyMAXqonuP5xK5x02F49a3Jo3W6RGT2sdNkGpNYIPD9T1EMHnj9Gj8CF3OhsPBt7eRzBYTLbQfwD7EvtCDd+kHPA8TXDdxqAeFJrES58EgEKoO24v6I7zJzWjN6QWYvRrMNvllPq6ELno1AntZxu0ugm5K/w9ZJfPLXDizJscZ3RLkPO7q9s22dtKASCiEauVTijxaTYHowZ9OvaK/jT+XljpOZUHuH/6GgL7c2dW/V1+ayFW812a55ZNdd9rZrTGRrlp1No36879rwTAunk75/24R/WfAI2mpp5nDURO1Zl4TujqxlKqTLkblaHdczDm8+zTu1K5T4syu0fwZUEQjwl9iOdHelSlNs/I3tkuJFCSJbibkGS2buZm3G2jrjJSLu8Z1M3XNvtu27lzOTnTe19mjVWA/kuIzOMF66PZU8OFhBc26JBtndKe/gBvbYIClrzoMhKdHzAFVrkQcI/BC9ErJCR,iv:ci0ZrQO9MGpqmxlgoFXiZpLrYUGdO203IFx2+7RSF+o=,tag:VM1QwU8li4umFwbfgmZdMw==,type:str]
authentik-ldap-env: ENC[AES256_GCM,data:pdzkicTb2UZBSkQLozijI1IRLWYQfJMrlzYa6JDFRTx/PKFWlxYTnyt3GKmyxD9BifDWE/26Wj0qV7MO2xhrRfrPACRoPPK03hdRiQW2BJvFCd8TylqYzxrEfzXQbD7/zm3sJ3pPEF/EDTvxZ+wcGXXXyTAyth3PvU42baArZCTaSnPPHys3FE8=,iv:+1AHRapUW1K162hP5UVeMq0oZyhUXwpRlYVZ+eUTrzY=,tag:ap56x+6mMgtSeUhMdEr+QA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age: []
lastmodified: "2024-04-25T05:21:19Z"
mac: ENC[AES256_GCM,data:SKgu8RkrEZjBlgQDl7XPtG41m33cNZaKBEswMNNIi78UHZwbUbo1Biblt6kvknObaFcDJn4j9zWtPnSDhPYUbIafNNQCHQY6w/fKX1hfBoJwGT66iLRBeOHYJcJVvIYfKeoVE0x8NnNoW4MqafPbgQF8v0PxNSDzCt/w9BL5OIw=,iv:0OPFQMAwxLTiDJ+nUe1rAvVjs2nB4P50IF65kULd/nM=,tag:I8wZa4k49Qti+5f6CB3DSg==,type:str]
lastmodified: "2024-04-26T03:11:57Z"
mac: ENC[AES256_GCM,data:tjxkEzNJBThDbizdbg8kQ/fVUU7i3gpc89C2QmqXHky9mzvzY2Ve9wL0FPJXMfvLNo5ZqOG5g03Eal8vYn+cDQwSJacdCSMS3ehoC/MjntWqU7+3zHJxyynHfTpLGLgyAPjK6XAv29WXSAiyUBUov3OHpaTGo+x9ZYul6V4BHYI=,iv:vsEG1OQ6CJqv/8+ITr4xtI+zn8aoDOa+q8FSWgpR5fo=,tag:VNRDqVOLILu5mYy4fRo2Fw==,type:str]
pgp:
- created_at: "2024-04-24T05:40:34Z"
enc: |-