summaryrefslogtreecommitdiff
path: root/sys/pki/ca.nix
blob: 0a0d3c21ccf2cf59b09ab28beaad864c2fce92a1 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
{ config, lib, pkgs, ... }:
with lib; let
  cfg = config.local.pki.ca;

  inherit (pkgs.buildPackages) openssl;

  certsType = leafOf: with lib.types; attrsOf (submodule ({ config, name, ... }: {
    options = {
      cert = mkOption {
        type = path;
        readOnly = true;
      };

      fingerprint.sha256 = mkOption {
        type = str;
        readOnly = true;
      };

      fullchain = mkOption {
        type = path;
        readOnly = true;
      };

      issuer = mkOption {
        type = nullOr str;
        readOnly = true;
      };

      path = mkOption {
        type = str;
        readOnly = true;
      };
    } // optionalAttrs (leafOf != null) {
      commonName = mkOption {
        type = str;
        readOnly = true;
      };
    } // optionalAttrs (leafOf == null) {
      crl = mkOption {
        type = path;
        readOnly = true;
      };

      certWithCrl = mkOption {
        type = path;
        readOnly = true;
      };

      leaves = mkOption {
        type = certsType name;
        readOnly = true;
      };
    };

    config = {
      fingerprint.sha256 = readFile (pkgs.runCommandNoCCLocal "cert-${config.path}-fprint-sha256" { } ''
        ${openssl}/bin/openssl x509 -in ${config.cert} -noout -sha256 -fingerprint \
          | sed 's/^.*=//' \
          | tr -d $'\n' \
          >$out
      '');

      fullchain = pkgs.writeText "${name}-fullchain-crl.pem"
        (concatStrings (map readFile
          (singleton (if leafOf != null then config.cert else config.certWithCrl)
            ++ optional (config.issuer != null) cfg.${config.issuer}.fullchain)));

      path = optionalString (config.issuer != null) (cfg.${config.issuer}.path + ".") + name;
    } // optionalAttrs (leafOf != null) {
      commonName = readFile (pkgs.runCommandNoCCLocal "cert-${config.path}-fprint-sha256" { } ''
        ${openssl}/bin/openssl x509 -in ${config.cert} -noout -subject -nameopt multiline \
          | grep commonName \
          | sed 's/^.*=\s*//' \
          | tr -d $'\n' \
          >$out
      '');

      issuer = leafOf;
    } // optionalAttrs (leafOf == null) {
      certWithCrl = pkgs.writeText "${name}-cert-crl.pem"
        (concatStrings (map readFile [ config.cert config.crl ]));
    };
  }));
in
{
  options.local.pki.ca = mkOption {
    type = certsType null;
    readOnly = true;
  };

  config.local.pki.ca = {
    home = {
      crl = ./public/home-crl.pem;
      cert = ./public/home-ca.pem;
      issuer = "root";

      leaves = {
        user-firefox.cert = ./public/home-user-firefox.pem;
      };
    };

    mail = {
      crl = ./public/mail-crl.pem;
      cert = ./public/mail-ca.pem;
      issuer = "root";

      leaves = {
        kiev.cert = ./public/mail-kiev.pem;
      };
    };

    root = {
      crl = ./public/root-crl.pem;
      cert = ./public/root-ca.pem;
      issuer = null;
      leaves = { };
    };
  };
}