Skip to content

Commit 4bb68cb

Browse files
author
David Arnold
committed
modules: introduce mkcert (development certification authority)
1 parent d2224d2 commit 4bb68cb

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

devshell.toml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,84 @@ category = "utilites"
4646
help = "golang linter"
4747
package = "golangci-lint"
4848
category = "linters"
49+
50+
# ============================================================================
51+
# Example of custom extensions NOT part of devshell, see also:
52+
# ============================================================================
53+
# ./modules/mkcert.nix
54+
# ============================================================================
55+
56+
[mkcert]
57+
enable = true
58+
root-ca.key = """
59+
-----BEGIN PRIVATE KEY-----
60+
MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCaTaCuxSm7yHTx
61+
8WBBrhyqAsjDYvjsUw10a61D1oJA6+uCiEMHr79Xj3XSM0hNZXr7Tny9peqKrs07
62+
TqmRY42gM6w/1Wn0Kl7ODwbTKTeSGczapq0wmd7b1ZtrI4d3Yj3djdgXxLlX+CoB
63+
O2jfdQSv5ObODBWXE7xEQNQgWdQ4Oquub+q+8tr96v77gzeCxrFQtDZN8kkm4UGd
64+
SBgjwrqmpZ8oIXT/EjO79lIivReZ8olcJgLERPwBNGoBmTv9DAzyZi2G6wcIti/k
65+
PjFNJ/DAVvXxhA0pmsyEnSgnZcTSwmWSrAOr+WTLkL7ghsv5DeIBeullafs6/fvQ
66+
MAqHDhe8lu4oFmHQ8z6Hqmb7tCrKnBZ2GMQoJARSAti6Lm7LjgXoDzd3KncTlUoH
67+
U5ERIfgZVDqBrZawvMJ8V6r7w+FLPwM9gwJqCLkYusUvcB46zdfgZM5z3gHLIhXF
68+
ofdexigkx5hML3h++Gd1Dol4YvtQmU+EbOi7EfVgdoyays7IfE8CAwEAAQKCAYEA
69+
hvzERkC7ysiJ7iLgt3TPJLf81FlgNLZPffq5ADDHkG4TgQUdxrqsJLifNT2h0fum
70+
Q/Wc0Pg2IA7eAjVFyKgT/QNXfByCbZUnjRK+QLq9H7YsbVgFCRCDU0Qii+7wErPC
71+
NXFiiyCRmHDEpoFHtL0VVZ9lfvo5ZQph2D/ykz6ilnJVQOwtq9CfXiVX3cYkKOcT
72+
teuB2lzMPBQxp5urapVvXlxjyOLEDGTrF1Nc9YEBBa+VFSU3pGZJI/CrkCxyu2Pv
73+
D9uJl9IkwCekQTM/rFJyxbtKSIIK9yPEvpB1mRvpahCp6WJribYNldaejif0doEK
74+
VahAU7eVQ/fA1qBAPQq5qGQC3aFq3rk0iyumrfBNTtSKOG/kqdgNcRdGV0j3yXFA
75+
qu3tq6sRn7G6uRhKPacExIpoVYzigt2J2M7kzfE+wTg+1IQiSv7cLI0guh+4bFWH
76+
b9fEaHNMlfUhdi+aNeZFih3flOXpSwVWRYeCdqjgv5u4DoW7GJO4i5xOSe4X+roR
77+
AoHBAMfd6OyeCsSl5ShxNZgJpEC0NQesrGK7c3liE5BQE/wzzClpIPeJuvJ/twu9
78+
q/X0E6Y1S4VtvOEj/wUkGEeZZaUtQQkI2beT1RYHUglOM+QZYijsroDK1oBmEHyN
79+
IUXAaaIIC4q0sOJMzdOwuBFbMANikEuIDc11v+ny/32A3iEzjz6qdXx9h0wMfSdh
80+
4Mx8jHtX1+GIRm+KvD5UjDYcDv6C7BVVgBWosQ6UUqbKnGFkajY//16GpI/Scujh
81+
me4ShwKBwQDFo8VwN8qSbNWqzdvlMIVJE25uBX8Sb+8iOIxHvch+mjDdNw7IvI5t
82+
jvIi1YR8FOLe6SA1R2RYzVfSgxFlOOCj2hgQJHnL8Bg+XOmsK64KyBaCBWg1/RRl
83+
6hpmvUEZS6pWgrpyxvQhhiouqpa1utlOJoKp94shYyVs2frW6rzjxtv/p30FwexL
84+
FUlX1RMkLbVWZkvQjtYe5dYL6ZJfuxvEz2o6ur2ENgcXKf91ilE01X63uA0zqqkS
85+
T37MUhD2kfkCgcAtj+z1Y+HYimj/Gy+4hRooleww37A8obblSPJkx5yGtdgo6IpX
86+
Y9J2TZ8Q0iBNZWLFVQjuVeHlASu1pFDUoaeGTBazVI0tSEofR3PwIx+5NAAojCwL
87+
uDHF+35upk2bdQ2fnm3jJOXd8NxLEdIkQsFjRCjYzx82Y01oq7iKh8Ibl4FkK7+0
88+
rXkWYRJ2091HQG1WAOR5yXMlIl9fZi7Adw0EAByJkIAub9JNHIrq8u1LVnTQAS7a
89+
AZ+qGbOQWz2YBCkCgcEAm63oLP/VckeGeveS+dKherFyr/lmYfiHzlXqsewdTRRZ
90+
3zaqT5avPj92HdhAdpjhKCNMOouU0JpXTjvt7OTDlm2JvNVulyT1g9IeQn9ZpaZ8
91+
jEiEENrcQXcI+tqit7ExaNmq0hRDY1DSU1YORvH6kCOnkwipsE/vv/FoM/hNd8JB
92+
svyUb3+UiIQo9KWjYUEb8QW9PHf20/nJBDMlGIFDW2DiVYaZF9aS+T0cu9KLKuns
93+
2fyBcaxBZ2n1AC64q/DJAoHABntjs8y2ANGtklJCcoeCz7NgFxRzZwg0Ff84uiPD
94+
nqih5L4Tz/xqKf5KvO2Kz0byg+exPLDLx7y6B93qDKyLiWVUtPyYaup20EeNp6ws
95+
1dPpcvNMOZx1pEr6RFI61fWFJPvgWBo8fTLOPBaPFd4xaIuVN6EWTQoUtERU5F5I
96+
+uFnisEETd9f1mVXTAyk6piNVmYxaHsF1Z9xmEWX6142/0kcQfoGfZQYmaYGQfOo
97+
xS044vroff+d0i4NxpOfBXyf
98+
-----END PRIVATE KEY-----
99+
"""
100+
root-ca.cert = """
101+
-----BEGIN CERTIFICATE-----
102+
MIIEzjCCAzagAwIBAgIRAKGyGtqQLfNkWqnQWQ5mhx0wDQYJKoZIhvcNAQELBQAw
103+
fzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSowKAYDVQQLDCFuaXhi
104+
bGRAbG9jYWxob3N0IChOaXggYnVpbGQgdXNlcikxMTAvBgNVBAMMKG1rY2VydCBu
105+
aXhibGRAbG9jYWxob3N0IChOaXggYnVpbGQgdXNlcikwHhcNMjEwMTI3MTg1NTM1
106+
WhcNMzEwMTI3MTg1NTM1WjB/MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQg
107+
Q0ExKjAoBgNVBAsMIW5peGJsZEBsb2NhbGhvc3QgKE5peCBidWlsZCB1c2VyKTEx
108+
MC8GA1UEAwwobWtjZXJ0IG5peGJsZEBsb2NhbGhvc3QgKE5peCBidWlsZCB1c2Vy
109+
KTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJpNoK7FKbvIdPHxYEGu
110+
HKoCyMNi+OxTDXRrrUPWgkDr64KIQwevv1ePddIzSE1levtOfL2l6oquzTtOqZFj
111+
jaAzrD/VafQqXs4PBtMpN5IZzNqmrTCZ3tvVm2sjh3diPd2N2BfEuVf4KgE7aN91
112+
BK/k5s4MFZcTvERA1CBZ1Dg6q65v6r7y2v3q/vuDN4LGsVC0Nk3ySSbhQZ1IGCPC
113+
uqalnyghdP8SM7v2UiK9F5nyiVwmAsRE/AE0agGZO/0MDPJmLYbrBwi2L+Q+MU0n
114+
8MBW9fGEDSmazISdKCdlxNLCZZKsA6v5ZMuQvuCGy/kN4gF66WVp+zr9+9AwCocO
115+
F7yW7igWYdDzPoeqZvu0KsqcFnYYxCgkBFIC2LoubsuOBegPN3cqdxOVSgdTkREh
116+
+BlUOoGtlrC8wnxXqvvD4Us/Az2DAmoIuRi6xS9wHjrN1+BkznPeAcsiFcWh917G
117+
KCTHmEwveH74Z3UOiXhi+1CZT4Rs6LsR9WB2jJrKzsh8TwIDAQABo0UwQzAOBgNV
118+
HQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUvFZHpiR1
119+
SsZgx18IXS4sV2goJwwwDQYJKoZIhvcNAQELBQADggGBAEhEXonraBKooVsYVdd6
120+
EuLD5LJ9rLuVN0QCOWzMDgqc1iHX+nTEjH6OctBpdGo+1RRE4UB1SHoaCW7LcJJx
121+
1UCPHvMTby2U0Y1E7NS9dOdt3slUQUF86KfecV8UfTLgqWvN8W3pdyNqk8X7g5FO
122+
vnoWMRXopNyI/AnnAfEMC2rA1+fgJXFIi7Ny5vHiPoaPolvULDU8gwcBPpGB80z0
123+
py4x/DcO4UoNB11fs2+XNV6UGHfLB1R1OJmhdCbEQ7cmIetg11ThuvD8YiomKb1O
124+
wJO5moU86AJ52o19C3AmYKsClhGwnGLGNgOslFIozRi7eSPX7B9UdEJUvj2tGkUE
125+
mpSjE6hTUtEinmuQ0gkf4jaqcWetJnhUVaNGsbixWdRtkNkvICkToCGhHXFKDGfr
126+
qrM5Rs0xtUAp91/DZ+vbPsuWzvRibCrck89vyg1lGemhMf8g34U1ocf5KlyLvO3c
127+
o3E+CRMwgG1IP4ktc63dfXPvbfN+lKjk1LVhMBPXeqhJ2A==
128+
-----END CERTIFICATE-----
129+
"""

modules/mkcert.nix

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{ lib, pkgs, config, ... }:
2+
with lib;
3+
let
4+
cfg = config.mkcert;
5+
6+
maybeReadFile = obj:
7+
if (builtins.typeOf obj == "path") then
8+
builtins.readFile obj
9+
else
10+
obj
11+
;
12+
13+
# These are all the options available for specifying a certificate/key file.
14+
rootCAOption = {
15+
key = mkOption {
16+
description = "Text or file of the root CA key to install";
17+
default = null;
18+
type = types.nullOr (types.either types.str types.path);
19+
};
20+
cert = mkOption {
21+
description = "Text or file of the root CA certificate to install";
22+
default = null;
23+
type = types.nullOr (types.either types.str types.path);
24+
};
25+
};
26+
27+
# A collection of development certificate authority files
28+
rootCADir =
29+
let
30+
adHoc = pkgs.runCommandLocal "rootCA" {} ''
31+
export CAROOT=$out
32+
${pkgs.mkcert}/bin/mkcert 2>/dev/null
33+
'';
34+
35+
isPreconfigured =
36+
assert assertMsg (
37+
cfg.root-ca != {} && cfg.root-ca.cert != null && cfg.root-ca.key != null
38+
) "[mkcert]: either set, both, root CA key and certificate or none.";
39+
(cfg.root-ca.key != null && cfg.root-ca.cert != null);
40+
41+
key = pkgs.writeText "rootCA-key.pem" (maybeReadFile cfg.root-ca.key);
42+
cert = pkgs.writeText "rootCA.pem" (maybeReadFile cfg.root-ca.cert);
43+
44+
preconfigured = pkgs.runCommand "rootCA" {} ''
45+
mkdir $out
46+
cp ${key} $out/${key.name}
47+
cp ${cert} $out/${cert.name}
48+
'';
49+
in
50+
if isPreconfigured then preconfigured else adHoc;
51+
52+
# Execute this script to install the project's development certificate authority
53+
install-mkcert-ca = pkgs.writeShellScriptBin "install-mkcert-ca" ''
54+
set -euo pipefail
55+
shopt -s nullglob
56+
57+
log() {
58+
IFS=$'\n' loglines=($*)
59+
for line in ${"$"}{loglines[@]}; do echo -e "[mkcert] $line" >&2; done
60+
}
61+
62+
# Set the CA root files directory for mkcert via env variable
63+
export CAROOT=${rootCADir}
64+
65+
# Install local CA into system, java and nss (includes Firefox) trust stores
66+
log "Install development CA into the system stores..."
67+
log $(sudo -K; ${pkgs.mkcert}/bin/mkcert -install 2>&1)
68+
log "root CA directory: $(${pkgs.mkcert}/bin/mkcert -CAROOT 2>&1)"
69+
70+
uninstall() {
71+
log $(${pkgs.mkcert}/bin/mkcert -uninstall 2>&1)
72+
}
73+
74+
# TODO: Uninstall when leaving the devshell
75+
# trap uninstall EXIT
76+
77+
'';
78+
in
79+
{
80+
options.mkcert = {
81+
enable = mkEnableOption "provide a development CA within the shell";
82+
83+
root-ca = mkOption {
84+
type = types.submodule { options = rootCAOption; };
85+
default = {};
86+
description = "preconfigure root CA files";
87+
example = literalExample "
88+
{
89+
key = ''
90+
-----BEGIN PRIVATE KEY-----
91+
...
92+
-----END PRIVATE KEY-----
93+
'';
94+
cert = ./path/tocert.pem;
95+
}
96+
";
97+
};
98+
};
99+
100+
config = mkIf cfg.enable {
101+
env = { CAROOT = "${rootCADir}"; };
102+
commands = [ { package = pkgs.mkcert; category = "certs"; } ];
103+
devshell = {
104+
packages = [ install-mkcert-ca ];
105+
startup.install-mkcert-ca.text = "
106+
$DEVSHELL_DIR/bin/install-mkcert-ca
107+
";
108+
};
109+
};
110+
}

modules/modules.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ let
1616
}];
1717
}
1818
./git-hooks.nix
19+
./mkcert.nix
1920
];
2021

2122
pkgsModule = { config, ... }: {

0 commit comments

Comments
 (0)