summaryrefslogtreecommitdiff
path: root/hostnix/elmo/oidc.nix
blob: b24b07004dffa04f3be493871cf8730ea7e30a0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
{ config, ... }:

{
  services.kanidm = {
    enableClient = true;
    enableServer = true;
    clientSettings = {
      uri = "https://ki.mou.fo";
    };
    serverSettings = {
      origin = "https://ki.mou.fo";
      domain = "ki.mou.fo";
      bindaddress = "[::1]:7368";
      trust_x_forward_for = true;
      # Kanidm requires TLS even behind a reverse proxy.
      tls_chain = "/run/credentials/kanidm.service/fullchain.pem";
      tls_key = "/run/credentials/kanidm.service/key.pem";
    };
  };

  systemd.services.kanidm = {
    # Kanidm runs as an unprivileged user that needs access to certificates.
    serviceConfig.LoadCredential = let
      certDir = config.security.acme.certs."ki.mou.fo".directory;
    in
    [
      "fullchain.pem:${certDir}/fullchain.pem"
      "key.pem:${certDir}/key.pem"
    ];
  };

  services.nginx.virtualHosts."ki.mou.fo" = {
    enableACME = true;
    forceSSL = true;
    locations."/".proxyPass = "https://[::1]:7368";
  };

  # The oauth2-proxy module has a magic nginx.virtualHosts option that rewrites
  # nginx configs. It can be heavy handed, but we use it for brevity. In
  # particular, it configures Traefik-like ForwardAuth authentication with
  # auth_request. Note if this resource is missing for whatever reason, the
  # module magic will fail open (auth_request unset).
  services.oauth2-proxy = {
    enable = true;
    cookie.domain = "mou.fo";
    nginx.domain = "op.mou.fo";
    setXauthrequest = true;  # let oauth2-proxy nginx module pass X-User/X-Email
    reverseProxy = true;
    # Example nestled in https://kanidm.github.io/kanidm/stable/examples/kubernetes_ingress.html
    provider = "oidc";
    clientID = "oauth2-proxy";
    oidcIssuerUrl = "https://ki.mou.fo/oauth2/openid/oauth2-proxy";
    # Sets OAUTH2_PROXY_COOKIE_SECRET and OAUTH2_PROXY_CLIENT_SECRET.
    keyFile = "/var/secrets/oauth2-proxy.env";
    # Ignore e-mail address.
    scope = "openid profile";
    email.domains = [ "*" ];
    extraConfig = {
      "code-challenge-method" = "S256";
      "whitelist-domain" = ".mou.fo";  # allowed redirects after authentication
      # https://github.com/oauth2-proxy/oauth2-proxy/issues/1612#issuecomment-1099217761
      "oidc-email-claim" = "sub";
    };
  };

  # Kludge to bring up after Kanidm (otherwise OIDC discovery fails). A simple
  # ordering dependency isn't enough because kandim.service is active before
  # Kanidm responds to requests. Kanidm starts up quickly enough that boot up
  # may work without this.
  systemd.services.oauth2-proxy.serviceConfig.RestartSec = 5;

  # It's somewhat overkill to assign oauth2-proxy its own domain. We can't use
  # Kanidm's though, because it uses the /oauth2 path which the oauth2-proxy
  # nginx module is hardcoded for (proxyPrefix is ignored); this module magic is
  # also why we do not need to explicitly specify proxyPass.
  services.nginx.virtualHosts."op.mou.fo" = {
    enableACME = true;
    forceSSL = true;
  };
}