mirror of
https://github.com/oddlama/nix-config.git
synced 2025-10-10 23:00:39 +02:00
feat: prepare sentinel for webapp oauth2 authentication
This commit is contained in:
parent
19acca7cba
commit
6b81ecd961
9 changed files with 145 additions and 68 deletions
51
README.md
51
README.md
|
@ -136,32 +136,39 @@ openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Recover admin account (server must not be running)
|
# Recover admin account (server must not be running)
|
||||||
> systemctl stop kanidm
|
systemctl stop kanidm
|
||||||
> kanidmd recover-account -c server.toml admin
|
kanidmd recover-account -c server.toml admin
|
||||||
AhNeQgKkwwEHZ85dxj1GPjx58vWsBU8QsvKSyYwUL7bz57bp
|
> AhNeQgKkwwEHZ85dxj1GPjx58vWsBU8QsvKSyYwUL7bz57bp
|
||||||
> systemctl start kanidm
|
systemctl start kanidm
|
||||||
# Login with recovered root account
|
# Login with recovered root account
|
||||||
> kanidm login --name admin
|
kanidm login --name admin
|
||||||
# Generate new credentials for idm_admin account
|
# Generate new credentials for idm_admin account
|
||||||
> kanidm service-account credential generate -D admin idm_admin
|
kanidm service-account credential generate -D admin idm_admin
|
||||||
Yk0W24SQGzkLp97DNxxExCcryDLvA7Q2dR0A7ZuaVQevLR6B
|
> Yk0W24SQGzkLp97DNxxExCcryDLvA7Q2dR0A7ZuaVQevLR6B
|
||||||
# Generate new oauth2 app for grafana
|
# Generate new oauth2 app for grafana
|
||||||
> kanidm group create grafana-access
|
kanidm group create grafana-access
|
||||||
> kanidm group create grafana-server-admins
|
kanidm group create grafana-server-admins
|
||||||
> kanidm group create grafana-admins
|
kanidm group create grafana-admins
|
||||||
> kanidm group create grafana-editors
|
kanidm group create grafana-editors
|
||||||
> kanidm system oauth2 create grafana "Grafana" https://grafana.${personalDomain}
|
kanidm system oauth2 create grafana "Grafana" https://grafana.${personalDomain}
|
||||||
> kanidm system oauth2 update-scope-map grafana grafana-access openid profile email
|
kanidm system oauth2 update-scope-map grafana grafana-access openid profile email
|
||||||
> kanidm system oauth2 update-sup-scope-map grafana grafana-server-admins server_admin
|
kanidm system oauth2 update-sup-scope-map grafana grafana-server-admins server_admin
|
||||||
> kanidm system oauth2 update-sup-scope-map grafana grafana-admins admin
|
kanidm system oauth2 update-sup-scope-map grafana grafana-admins admin
|
||||||
> kanidm system oauth2 update-sup-scope-map grafana grafana-editors editor
|
kanidm system oauth2 update-sup-scope-map grafana grafana-editors editor
|
||||||
> kanidm system oauth2 show-basic-secret grafana
|
kanidm system oauth2 show-basic-secret grafana
|
||||||
|
# Generate new oauth2 app for proxied webapps
|
||||||
|
kanidm group create web-sentinel-access
|
||||||
|
kanidm group create web-sentinel-adguardhome-access
|
||||||
|
kanidm system oauth2 create web-sentinel "Web services" https://sentinel.${personalDomain}
|
||||||
|
kanidm system oauth2 update-scope-map web-sentinel web-sentinel-access openid profile email
|
||||||
|
kanidm system oauth2 update-sup-scope-map web-sentinel web-sentinel-adguardhome-access access_adguardhome
|
||||||
|
kanidm system oauth2 show-basic-secret web-sentinel
|
||||||
# Add new user
|
# Add new user
|
||||||
> kanidm login --name idm_admin
|
kanidm login --name idm_admin
|
||||||
> kanidm person create myuser "My User"
|
kanidm person create myuser "My User"
|
||||||
> kanidm person update myuser --legalname "Full Name" --mail "myuser@example.com"
|
kanidm person update myuser --legalname "Full Name" --mail "myuser@example.com"
|
||||||
> kanidm group add_members grafana-access myuser
|
kanidm group add-members grafana-access myuser
|
||||||
> kanidm group add_members grafana-server-admins myuser
|
kanidm group add-members grafana-server-admins myuser
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
42
flake.lock
generated
42
flake.lock
generated
|
@ -31,11 +31,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687090623,
|
"lastModified": 1687304097,
|
||||||
"narHash": "sha256-LdlH20WGKY1ebO3YJ85gPgmMPlGJUP4JUdqM+k5MsZw=",
|
"narHash": "sha256-VId0oZxpYm4HSHwbsuGKI84zFkL6Gp4wuoJbbl52oZg=",
|
||||||
"owner": "oddlama",
|
"owner": "oddlama",
|
||||||
"repo": "agenix-rekey",
|
"repo": "agenix-rekey",
|
||||||
"rev": "317558abbec903324e6d38393e2e84b42c25f479",
|
"rev": "b1811920562ba287b680f35644ce3ed78d029cdf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -119,11 +119,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687028856,
|
"lastModified": 1687134796,
|
||||||
"narHash": "sha256-vKV3I31tmXwaWHiUOgfDVd27cEHqaPBr1lt9+NKdIp8=",
|
"narHash": "sha256-gjBAkEtNPMQzqK4IHjTQBUv3VhggszOHLJbhXZy0OVQ=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "disko",
|
"repo": "disko",
|
||||||
"rev": "64c9c78c15fd4c899d857bf09dba88bda771b43a",
|
"rev": "4823509bb3b014dc85abefc13efcfa076d36338a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -169,11 +169,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1685518550,
|
"lastModified": 1687171271,
|
||||||
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
"narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
"rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -210,11 +210,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687081547,
|
"lastModified": 1687301540,
|
||||||
"narHash": "sha256-/JV70TxhvP2r4xYtTlbQ2rrRDcj7MqHnF13r5ZE0oFc=",
|
"narHash": "sha256-vFbCrE9WlOSVpyAT5VNR3bqMB7W7sDzMNDcO6JqtmBw=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "28c823032cabfaa340a09e1d84cf45d11375c644",
|
"rev": "9a76fb9a852fdf9edd3b0aabc119efa1d618f969",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -275,11 +275,11 @@
|
||||||
},
|
},
|
||||||
"nixlib": {
|
"nixlib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1685840432,
|
"lastModified": 1687049841,
|
||||||
"narHash": "sha256-VJIbiKsY7Xy4E4WcgwUt/UiwYDmN5BAk8tngAjcWsqY=",
|
"narHash": "sha256-FBNZQfWtA7bb/rwk92mfiWc85x4hXta2OAouDqO5W8w=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixpkgs.lib",
|
"repo": "nixpkgs.lib",
|
||||||
"rev": "961e99baaaa57f5f7042fe7ce089a88786c839f4",
|
"rev": "908af6d1fa3643c5818ea45aa92b21d6385fbbe5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -296,11 +296,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1686924781,
|
"lastModified": 1687183443,
|
||||||
"narHash": "sha256-6r3Hm2Fxf4F7LIWRYKU9bsS/xJwlG6L2+/I/pdffvOs=",
|
"narHash": "sha256-foX4pkph2AwUdJL3JURa7IHog+YRIheZ54vwHwxqwhU=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixos-generators",
|
"repo": "nixos-generators",
|
||||||
"rev": "a54683aa7eff00ee5b33dec225525d0eb6ab02de",
|
"rev": "09140f23f5ffce828db4ef040070bdd9595b1f3a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -388,11 +388,11 @@
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1686668298,
|
"lastModified": 1687251716,
|
||||||
"narHash": "sha256-AADh9NqHh6X2LOem4BvI7oCkMm+JPCSCE7iIw5nn0VA=",
|
"narHash": "sha256-+sFS41thsB5U+lY/dBYPSmU4AJ7nz/VdM1WD35fXVeM=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "pre-commit-hooks.nix",
|
"repo": "pre-commit-hooks.nix",
|
||||||
"rev": "5b6b54d3f722aa95cbf4ddbe35390a0af8c0015a",
|
"rev": "7807e1851d95828ed98491930d2d9e7ddbe65da4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -362,6 +362,25 @@
|
||||||
lib.mkIf (pubkeyPath != null && lib.pathExists pubkeyPath) pubkeyPath;
|
lib.mkIf (pubkeyPath != null && lib.pathExists pubkeyPath) pubkeyPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
age.generators.basic-auth.script = {
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
decrypt,
|
||||||
|
deps,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
lib.flip lib.concatMapStrings deps ({
|
||||||
|
name,
|
||||||
|
host,
|
||||||
|
file,
|
||||||
|
}: ''
|
||||||
|
echo " -> Aggregating [32m"${lib.escapeShellArg host}":[m[33m"${lib.escapeShellArg name}"[m" >&2
|
||||||
|
echo -n ${lib.escapeShellArg host}"+"${lib.escapeShellArg name}" "
|
||||||
|
${decrypt} ${lib.escapeShellArg file} \
|
||||||
|
| ${pkgs.caddy}/bin/caddy hash-password --algorithm bcrypt \
|
||||||
|
|| die "Failure while aggregating caddy basic auth hashes"
|
||||||
|
'');
|
||||||
|
|
||||||
boot = {
|
boot = {
|
||||||
initrd.systemd = {
|
initrd.systemd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
|
||||||
nodes,
|
|
||||||
nodeName,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
users.groups.acme.members = ["caddy"];
|
users.groups.acme.members = ["caddy"];
|
||||||
|
|
||||||
services.caddy = {
|
age.secrets.caddy-env = {
|
||||||
|
rekeyFile = ./secrets/caddy-env.age;
|
||||||
|
mode = "440";
|
||||||
|
group = "caddy";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.caddy = let
|
||||||
|
proxyAuthDomain = "sentinel.${config.repo.secrets.local.personalDomain}";
|
||||||
|
in {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.caddy.withPackages {
|
package = pkgs.caddy.withPackages {
|
||||||
plugins = [
|
plugins = [
|
||||||
|
@ -19,5 +24,52 @@
|
||||||
];
|
];
|
||||||
vendorHash = "sha256-RqSXQihtY5+ACaMo7bLdhu1A+qcraexb1W/Ia+aUF1k";
|
vendorHash = "sha256-RqSXQihtY5+ACaMo7bLdhu1A+qcraexb1W/Ia+aUF1k";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtualHosts.${proxyAuthDomain} = {
|
||||||
|
useACMEHost = config.lib.extra.matchingWildcardCert proxyAuthDomain;
|
||||||
|
extraConfig = ''
|
||||||
|
import common
|
||||||
|
authenticate with myportal
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
globalConfig = ''
|
||||||
|
order authenticate before respond
|
||||||
|
order authorize before basicauth
|
||||||
|
|
||||||
|
security {
|
||||||
|
oauth identity provider kanidm {
|
||||||
|
realm kanidm
|
||||||
|
driver generic
|
||||||
|
client_id web-sentinel
|
||||||
|
client_secret {env.KANIDM_CLIENT_SECRET}
|
||||||
|
scopes openid email profile
|
||||||
|
base_auth_url https://${config.proxiedDomains.kanidm}/ui/oauth2
|
||||||
|
metadata_url https://${config.proxiedDomains.kanidm}/oauth2/openid/sentinel/.well-known/openid-configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication portal myportal {
|
||||||
|
enable identity provider kanidm
|
||||||
|
cookie domain ${config.repo.secrets.local.personalDomain}
|
||||||
|
ui {
|
||||||
|
links {
|
||||||
|
"My Identity" "/whoami" icon "las la-user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transform user {
|
||||||
|
match realm kanidm
|
||||||
|
action add role authp/user
|
||||||
|
}
|
||||||
|
|
||||||
|
#transform user {
|
||||||
|
# match realm kanidm
|
||||||
|
# match scope read:access_aguardhome
|
||||||
|
# action add role authp/admin
|
||||||
|
#}
|
||||||
|
}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.caddy.serviceConfig.environmentFile = config.age.secrets.caddy-env.path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,9 @@
|
||||||
./acme.nix
|
./acme.nix
|
||||||
./caddy.nix
|
./caddy.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
extra.promtail = {
|
||||||
|
enable = true;
|
||||||
|
proxy = "sentinel";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
BIN
hosts/sentinel/secrets/caddy-env.age
Normal file
BIN
hosts/sentinel/secrets/caddy-env.age
Normal file
Binary file not shown.
11
hosts/sentinel/secrets/promtail-loki-basic-auth-password.age
Normal file
11
hosts/sentinel/secrets/promtail-loki-basic-auth-password.age
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
age-encryption.org/v1
|
||||||
|
-> X25519 5yDq2pctzyK8uUxKxekOz9tHbmUq4JKCzEbBCYQ79w0
|
||||||
|
lFsTmuUufwYoZ1fAbs7BCmaU3h6Mck8w98TmUdahWP8
|
||||||
|
-> piv-p256 xqSe8Q Aul+3eIiUD0DWAiRPR7Ms4l9ohF+62P98EYqngOFOwU9
|
||||||
|
TdW4WUaIeT7rC9eeGjEM1jPEp/LE1q2V3/fQFLyjbtk
|
||||||
|
-> yYnni-grease 2a
|
||||||
|
SV/4RAhtPi8LsDwcXpwT8AZQCwwJ1tu0R3aN8r7J5cs2RCNGKvNYhU3WRZ6XUi84
|
||||||
|
S1SGmd886W3twPhMYSjm9j8IqqJ5iaWq0IXPpxLZIpv1viS4jDoLgMcKxFbKI97z
|
||||||
|
5OCc
|
||||||
|
--- 30SxKU9DX+vU3e/fd4upxOLcv4DSujy06P+Ja2yHPjM
|
||||||
|
¾?ÙGu>ir7åyÛ¦mé–`Ç‘·"AêM7´^…ì�÷‘ÏM*ÿO%BÜÁÂRµQ©Â“§^Hxï_ÑÎ;e‚ü—ÃdW�3†q0\ª4:Ü
|
|
@ -26,27 +26,9 @@ in {
|
||||||
|
|
||||||
age.secrets.loki-basic-auth-hashes = {
|
age.secrets.loki-basic-auth-hashes = {
|
||||||
rekeyFile = ./secrets/loki-basic-auth-hashes.age;
|
rekeyFile = ./secrets/loki-basic-auth-hashes.age;
|
||||||
generator = {
|
# Copy only the script so the dependencies can be added by the nodes
|
||||||
# Dependencies are added by the nodes that define passwords (using distributed-config).
|
# that define passwords (using distributed-config).
|
||||||
script = {
|
generator.script = config.age.generators.basic-auth.script;
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
decrypt,
|
|
||||||
deps,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
lib.flip lib.concatMapStrings deps ({
|
|
||||||
name,
|
|
||||||
host,
|
|
||||||
file,
|
|
||||||
}: ''
|
|
||||||
echo " -> Aggregating [32m"${lib.escapeShellArg host}":[m[33m"${lib.escapeShellArg name}"[m" >&2
|
|
||||||
echo -n ${lib.escapeShellArg host}"+"${lib.escapeShellArg name}" "
|
|
||||||
${decrypt} ${lib.escapeShellArg file} \
|
|
||||||
| ${pkgs.caddy}/bin/caddy hash-password --algorithm bcrypt \
|
|
||||||
|| die "Failure while aggregating caddy basic auth hashes"
|
|
||||||
'');
|
|
||||||
};
|
|
||||||
mode = "440";
|
mode = "440";
|
||||||
group = "caddy";
|
group = "caddy";
|
||||||
};
|
};
|
||||||
|
@ -55,6 +37,7 @@ in {
|
||||||
useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert lokiDomain;
|
useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert lokiDomain;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
import common
|
import common
|
||||||
|
skip_log
|
||||||
basicauth {
|
basicauth {
|
||||||
import ${sentinelCfg.age.secrets.loki-basic-auth-hashes.path}
|
import ${sentinelCfg.age.secrets.loki-basic-auth-hashes.path}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue