56 lines
2.4 KiB
Nix
56 lines
2.4 KiB
Nix
{ nixpkgs ? import <nixpkgs> }: let
|
|
pkgs = nixpkgs;
|
|
lib = nixpkgs.lib;
|
|
defaultCertTemplate = {
|
|
serial = 1;
|
|
activation_date = "1970-01-01 00:00:00 UTC";
|
|
expiration_date = "2500-01-01 00:00:00 UTC";
|
|
};
|
|
keyValToConfigLines = (key: value:
|
|
if (builtins.isString value) || (builtins.isPath value) then "${key} = \"${value}\"" else
|
|
if builtins.isInt value then "${key} = ${builtins.toString value}" else
|
|
if builtins.isList value then map (innerValue: keyValToConfigLines key innerValue) else
|
|
if builtins.isBool value then (if value then "${key}" else "# no ${key}") else
|
|
throw "don't know how to handle ${builtins.typeOf value}"
|
|
);
|
|
mkTemplateConfig = config: lib.concatStringsSep "\n" (lib.lists.flatten (lib.attrsets.mapAttrsToList keyValToConfigLines config));
|
|
certCfg = pkgs.writeText "deterministic-cert.cfg" ''
|
|
serial = 1
|
|
activation_date = "1970-01-01 00:00:00 UTC"
|
|
expiration_date = "2500-01-01 00:00:00 UTC"
|
|
'';
|
|
privKeyFile = name: let
|
|
keySizeBits = 256;
|
|
keySizeHex = builtins.toString (keySizeBits / 4);
|
|
in pkgs.runCommand "deterministic-privkey-${name}.pem" {} ''
|
|
seed=$(echo ${lib.escapeShellArg (builtins.toJSON name)} | ${pkgs.ruby_3_2}/bin/ruby -rjson -e 'name = JSON.parse(STDIN.gets); print name.unpack("H*")[0].ljust(${keySizeHex}, "0")')
|
|
${pkgs.gnutls}/bin/certtool --generate-privkey --outfile=$out --key-type=rsa --sec-param=high --seed=$seed
|
|
'';
|
|
generateCert = { name, config, args, preCommands ? "" }: let
|
|
deriv = pkgs.runCommand "deterministic-cert-${name}" {} ''
|
|
mkdir -p $out
|
|
cd $out
|
|
ln -s ${privKeyFile name} privkey.pem
|
|
ln -s ${pkgs.writeText "${name}-template.cfg" (mkTemplateConfig (defaultCertTemplate // config))} template.cfg
|
|
${preCommands}
|
|
${pkgs.gnutls}/bin/certtool ${lib.escapeShellArgs args} --load-privkey=privkey.pem --outfile=cert.pem --template=template.cfg
|
|
'';
|
|
in deriv // { privateKeyPath = "${deriv}/privkey.pem"; certificatePath = "${deriv}/cert.pem"; };
|
|
|
|
in {
|
|
inherit privKeyFile;
|
|
selfSigned = name: config: generateCert { inherit name config; args = [ "--generate-self-signed" ]; };
|
|
caSigned = name: ca: config: generateCert {
|
|
inherit name config;
|
|
preCommands = ''
|
|
ln -s ${ca.privateKeyPath} ca-privkey.pem
|
|
ln -s ${ca.certificatePath} ca-cert.pem
|
|
'';
|
|
args = [
|
|
"--generate-certificate"
|
|
"--load-ca-certificate=ca-cert.pem"
|
|
"--load-ca-privkey=ca-privkey.pem"
|
|
];
|
|
};
|
|
}
|