feat: add RFC 7033 support with new service and package
Python webserver to serve RFC7033 since Authentik does not support it. This is needed for OICD login in Tailscale
This commit is contained in:
parent
8b72b206ce
commit
f664873ced
3 changed files with 116 additions and 2 deletions
|
|
@ -6,6 +6,10 @@
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.my.services.authentik;
|
cfg = config.my.services.authentik;
|
||||||
|
|
||||||
|
# https://github.com/goauthentik/authentik/issues/5440#issuecomment-1682856454
|
||||||
|
# Needed for Tailscale
|
||||||
|
rfc-7033 = pkgs.callPackage ../../packages/authentik-rfc7033/default.nix { };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -101,14 +105,48 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 9000 ];
|
# Add your package to system packages
|
||||||
|
environment.systemPackages = [ rfc-7033 ];
|
||||||
|
|
||||||
|
# Systemd service configuration
|
||||||
|
systemd.services.authentik-rfc-7033 = {
|
||||||
|
description = "Pyhton webserver to implement RFC 7033";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${pkgs.python3}/bin/python ${rfc-7033}/bin/rfc-7033.py";
|
||||||
|
Restart = "on-failure";
|
||||||
|
User = "nobody"; # Or specify a user
|
||||||
|
Group = "nogroup";
|
||||||
|
# Optional: Log output to journalctl
|
||||||
|
StandardOutput = "journal";
|
||||||
|
StandardError = "journal";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Port 8000 is for RFC 7033
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
8000
|
||||||
|
9000
|
||||||
|
];
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
(lib.mkIf cfg.proxy.enable {
|
(lib.mkIf cfg.proxy.enable {
|
||||||
services.caddy = with cfg.proxy; {
|
services.caddy = with cfg.proxy; {
|
||||||
virtualHosts."${subdomain}.${domain}".extraConfig = ''
|
virtualHosts."${subdomain}.${domain}".extraConfig = ''
|
||||||
reverse_proxy http://${host}:9000
|
# Other reverse proxies go here
|
||||||
|
handle {
|
||||||
|
reverse_proxy http://${host}:9000
|
||||||
|
}
|
||||||
|
|
||||||
|
import cloudflare_${domain}
|
||||||
|
'';
|
||||||
|
virtualHosts."${domain}".extraConfig = ''
|
||||||
|
handle /.well-known/webfinger {
|
||||||
|
# This should point to the port that the Python script is running on, default is 8000
|
||||||
|
reverse_proxy http://${host}:8000
|
||||||
|
}
|
||||||
|
|
||||||
import cloudflare_${domain}
|
import cloudflare_${domain}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
||||||
15
packages/authentik-rfc7033/default.nix
Normal file
15
packages/authentik-rfc7033/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
pkgs ? import <nixpkgs> { },
|
||||||
|
}:
|
||||||
|
|
||||||
|
pkgs.stdenv.mkDerivation rec {
|
||||||
|
name = "authentik-rfc7033";
|
||||||
|
src = ./src;
|
||||||
|
|
||||||
|
buildInputs = [ pkgs.python3 ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
install -Dm755 rfc-7033.py $out/bin/rfc-7033.py
|
||||||
|
patchShebangs $out/bin/rfc-7033.py
|
||||||
|
'';
|
||||||
|
}
|
||||||
61
packages/authentik-rfc7033/src/rfc-7033.py
Normal file
61
packages/authentik-rfc7033/src/rfc-7033.py
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
|
from urllib.parse import urlparse, parse_qs
|
||||||
|
import json
|
||||||
|
|
||||||
|
class WebFingerHandler(BaseHTTPRequestHandler):
|
||||||
|
def do_GET(self):
|
||||||
|
if self.path.startswith('/.well-known/webfinger'):
|
||||||
|
parsed_url = urlparse(self.path)
|
||||||
|
query_params = parse_qs(parsed_url.query)
|
||||||
|
|
||||||
|
if 'resource' in query_params:
|
||||||
|
resource = query_params['resource'][0]
|
||||||
|
|
||||||
|
if resource.startswith('acct:'):
|
||||||
|
email = resource[5:]
|
||||||
|
issuer_url = "https://auth.pasetto.me/application/o/tailscale/"
|
||||||
|
response_data = {
|
||||||
|
"subject": resource,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||||
|
"href": issuer_url
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "authorization_endpoint",
|
||||||
|
"href": issuer_url + "oauth2/authorize"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "token_endpoint",
|
||||||
|
"href": issuer_url + "oauth2/token"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "userinfo_endpoint",
|
||||||
|
"href": issuer_url + "userinfo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "jwks_uri",
|
||||||
|
"href": issuer_url + "jwks"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/json")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps(response_data).encode())
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_response(404)
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(b"Resource not found")
|
||||||
|
|
||||||
|
def run_server(server_class=HTTPServer, handler_class=WebFingerHandler, port=8000):
|
||||||
|
server_address = ('', port)
|
||||||
|
httpd = server_class(server_address, handler_class)
|
||||||
|
print(f"Starting WebFinger server on port {port}")
|
||||||
|
httpd.serve_forever()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run_server()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue