Skip to content
Snippets Groups Projects
Commit 19eedc0b authored by Jean-Paul Calderone's avatar Jean-Paul Calderone
Browse files

enable tls with acme certificates

parent 0c7c27ac
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,23 @@ in {
The package to use for the ZKAP issuer.
'';
};
services.private-storage-issuer.domain = lib.mkOption {
default = "payments.privatestorage.io";
type = lib.types.str;
example = lib.literalExample "payments.example.com";
description = ''
The domain name at which the issuer is reachable.
'';
};
services.private-storage-issuer.tls = lib.mkOption {
default = true;
type = lib.types.bool;
description = ''
Whether or not to listen on TLS. For real-world use you should always
listen on TLS. This is provided as an aid to automated testing where
it might be difficult to obtain a real certificate.
'';
};
services.private-storage-issuer.issuer = lib.mkOption {
default = "Ristretto";
type = lib.types.enum [ " Trivial" "Ristretto" ];
......@@ -49,13 +66,22 @@ in {
};
};
config = lib.mkIf cfg.enable {
config =
let
acme = "/var/lib/acme";
in lib.mkIf cfg.enable {
# Add a systemd service to run PaymentServer.
systemd.services.zkapissuer = {
enable = true;
description = "ZKAP Issuer";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
after = [
# Make sure there is a network so we can bind to all of the
# interfaces.
"network.target"
];
# Make sure we at least have a self-signed certificate.
requires = lib.optional cfg.tls "acme-selfsigned-${cfg.domain}.service";
serviceConfig = {
ExecStart =
......@@ -70,8 +96,21 @@ in {
if cfg.database == "Memory"
then "--database Memory"
else "--database SQLite3 --database-path ${cfg.databasePath}";
httpsArgs =
if cfg.tls
then
"--https-port 443 " +
# acme has plugins to write the files in different ways but the
# self-signed certificate generator doesn't. The files it
# writes are weirdly named and shaped but they work.
"--https-certificate-path ${acme}/${cfg.domain}/full.pem " +
"--https-certificate-chain-path ${acme}/${cfg.domain}/fullchain.pem " +
"--https-key-path ${acme}/${cfg.domain}/key.pem"
else
# Only for automated testing.
"--http-port 80";
in
"${cfg.package}/bin/PaymentServer-exe ${issuerArgs} ${databaseArgs}";
"${cfg.package}/bin/PaymentServer-exe ${issuerArgs} ${databaseArgs} ${httpsArgs}";
Type = "simple";
# It really shouldn't ever exit on its own! If it does, it's a bug
# we'll have to fix. Restart it and hope it doesn't happen too much
......@@ -79,5 +118,42 @@ in {
Restart = "always";
};
};
# Certificate renewal. Note that preliminarySelfsigned only creates the
# service. We must declare that we *require* it in our service above.
security.acme = if cfg.tls
then {
production = false;
preliminarySelfsigned = true;
certs."${cfg.domain}" = {
email = "jean-paul@privatestorage.io";
postRun = "systemctl restart zkapissuer.service";
webroot = "${acme}/acme-challenges";
plugins = [ "full.pem" "fullchain.pem" "key.pem" ];
};
}
else {};
systemd.timers = if cfg.tls
then {
"acme-${cfg.domain}-initial" = config.systemd.timers."acme-${cfg.domain}" // {
timerConfig = {
OnUnitActiveSec = "0";
Unit = "acme-${cfg.domain}.service";
Persistent = "yes";
AccuracySec = "1us";
RandomizedDelaySec = "0s";
};
};
}
else {};
services.nginx.virtualHosts = if cfg.tls
then {
"${cfg.domain}" = {
locations."/" = "${acme}/acme-challenges";
};
}
else {};
};
}
......@@ -13,15 +13,19 @@ from time import sleep
def main():
clientAPIRoot, issuerAPIRoot = argv[1:]
if not clientAPIRoot.endswith("/"):
clientAPIRoot += "/"
if not issuerAPIRoot.endswith("/"):
issuerAPIRoot += "/"
# Construct a voucher that's acceptable to various parts of the system.
voucher = "a" * 44
zkapauthz = clientAPIRoot + "/storage-plugins/privatestorageio-zkapauthz-v1"
zkapauthz = clientAPIRoot + "storage-plugins/privatestorageio-zkapauthz-v1"
# Simulate a payment for a voucher.
post(
issuerAPIRoot + "/v1/stripe/webhook",
issuerAPIRoot + "v1/stripe/webhook",
dumps(charge_succeeded_json(voucher)),
headers={"content-type": "application/json"},
)
......
......@@ -10,7 +10,7 @@ let
exercise-storage = ./exercise-storage.py;
# The root URL of the Ristretto-flavored PrivacyPass issuer API.
issuerURL = "http://issuer:8081/";
issuerURL = "http://issuer/";
# The issuer's signing key. Notionally, this is a secret key. This is only
# the value for this system test though so I don't care if it leaks to the
......@@ -81,6 +81,8 @@ import <nixpkgs/nixos/tests/make-test.nix> {
];
services.private-storage-issuer = {
enable = true;
domain = "issuer";
tls = false;
issuer = "Ristretto";
inherit ristrettoSigningKey;
};
......@@ -140,7 +142,7 @@ import <nixpkgs/nixos/tests/make-test.nix> {
# Get some ZKAPs from the issuer.
eval {
$client->succeed('set -eo pipefail; ${get-passes} http://127.0.0.1:3456 http://issuer:8081 | systemd-cat');
$client->succeed('set -eo pipefail; ${get-passes} http://127.0.0.1:3456 ${issuerURL} | systemd-cat');
# succeed() is not success but 1 is.
1;
} or do {
......
......@@ -4,6 +4,6 @@ in
pkgs.fetchFromGitHub {
owner = "PrivateStorageio";
repo = "PaymentServer";
rev = "028d26152eba4f034aba405caa17627a764c2bbe";
sha256 = "06hdln97r2ign7phf661wlzh3z06bk9906lvc0gm3lh1pa23d3gb";
rev = "0acf43493a7525b0eba01b1c69fb69b41f411ecc";
sha256 = "0zaqm6qmylclxn25vghafwqxpm5h13c727x3zjnqgp7vbmi2aglk";
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment