Skip to content

Instantly share code, notes, and snippets.

@dirkx
Created December 31, 2019 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dirkx/e4dc43ebcea0b3f372f5d6a3dce302e5 to your computer and use it in GitHub Desktop.
Save dirkx/e4dc43ebcea0b3f372f5d6a3dce302e5 to your computer and use it in GitHub Desktop.
updated example - more in line with other tests
# Note -- this assumes bash - not the bourne shell.
#
import ../nixpkgs-test/nixos/tests/make-test-python.nix ({ pkgs, ... }:
let
tsWebRoot = "/data/http/ts";
in
{
name = "redwax";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ dirkx ];
};
machine =
{ config, ... }:
{ networking.firewall.enable = true;
networking.firewall.rejectPackets = true;
networking.firewall.allowPing = true;
networking.firewall.allowedTCPPorts = [ 443 ];
networking.extraHosts = ''
${config.networking.primaryIPAddress} tts.local
'';
services.httpd = {
enable = true;
adminAddr = "admin@tts.local";
extraModules = [
{ name = "ca"; path = "${pkgs.apacheHttpdPackages.mod_ca}/modules/mod_ca.so"; }
{ name = "ca_simple"; path = "${pkgs.apacheHttpdPackages.mod_ca}/modules/mod_ca_simple.so"; }
{ name = "timestamp"; path = "${pkgs.apacheHttpdPackages.mod_timestamp}/modules/mod_timestamp.so"; }
];
virtualHosts = {
"tts.local" = {
documentRoot = tsWebRoot;
forceSSL = true;
sslServerKey = "${tsWebRoot}/keys/server.key";
sslServerCert = "${tsWebRoot}/keys/server.pem";
extraConfig = ''
Header always set Strict-Transport-Security "max-age=15552000"
# backend configuration:
#
<IfModule mod_ca_simple.c>
# use system clock as the time source
CASimpleTime on
# assign a random serial number
CASimpleSerialRandom on
</IfModule>
# frontend configuration
<IfModule mod_timestamp.c>
<Location /timestamp>
SetHandler timestamp
TimestampSigningCertificate "${tsWebRoot}/keys/ts-service.pem"
TimestampSigningKey "${tsWebRoot}/keys/ts-service.key"
TimestampDigest SHA256
TimestampDefaultPolicy 1.2.3.4.5
Require all granted
</Location>
</IfModule>
'';
};
};
};
environment.systemPackages = [ pkgs.openssl ];
system.activationScripts.createDummyKey = ''
set -xe
dir="${tsWebRoot}/keys"
mkdir -m 0700 -p $dir
# We need to construct two certificates; one for the web server (optional; http fine too)
# and one for the time stamping sevice. See section 2.1/#11 of RFC 3161 for the rationale
# behind separate keys/certs ((https://tools.ietf.org/html/rfc3161).
# Generating CA - and use that to sign a server and service cert.
#
${pkgs.openssl}/bin/openssl req -new -x509 -nodes -newkey rsa:1024 \
-extensions v3_ca \
-subj "/C=NL/ST=Zuid-Holland/L=Leiden/O=Koelie-Kerk/CN=CA" \
-out $dir/ca.pem -keyout $dir/ca.key
# Generating key for server. We are a bit pedantic about subjectAltNames as
# some enterprise tools that use time-stamping severs seem to be strict on this.
#
${pkgs.openssl}/bin/openssl req -new -nodes -newkey rsa:1024 -keyout $dir/server.key \
-subj "/C=NL/ST=Zuid-Holland/L=Leiden/O=Koelie-Kerk/CN=tts.local" \
-extensions v3_req \
-addext subjectAltName=DNS:tts.local \
-out $dir/temp.csr
# We're generating a v3 cert (as we need subjectAltName); which does
# not have the requered extension block in the default openssl.cnf. So
# we generate one.
#
cat > $dir/extfile.cnf <<EOM
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
EOM
${pkgs.openssl}/bin/openssl x509 -req -days 14 -set_serial 2 \
-CA $dir/ca.pem -CAkey $dir/ca.key \
-extension usr_cert \
-extfile $dir/extfile.cnf \
-in $dir/temp.csr \
-out $dir/server.pem
rm $dir/temp.csr $dir/extfile.cnf
# Generating key for service
#
${pkgs.openssl}/bin/openssl req -new -nodes -newkey rsa:1024 -keyout $dir/ts-service.key \
-subj "/C=NL/ST=Zuid-Holland/L=Leiden/O=Koelie-Kerk/CN=Grote klokken doen bim-bam - timestamps service" \
-out $dir/temp.csr
# The signed cert needs timestamping as a critical usage extension.
#
echo extendedKeyUsage=critical,timeStamping > $dir/extfile.cnf
${pkgs.openssl}/bin/openssl x509 -req -days 14 -set_serial 3 \
-CA $dir/ca.pem -CAkey $dir/ca.key \
-extfile $dir/extfile.cnf \
-in $dir/temp.csr \
-in $dir/temp.csr \
-out $dir/ts-service.pem
rm $dir/temp.csr $dir/extfile.cnf
# CA key not needed from this point onwards.
#
rm $dir/ca.key
# We need a chain to verify the signature on the timestamp.
#
cat $dir/ts-service.pem $dir/ca.pem > $dir/fullchain-ts-service.pem
'';
};
testScript = ''
start_all()
machine.wait_for_unit("httpd.service")
# generate a file to sign
machine.succeed("dd if=/dev/urandom of=data.raw count=1 bs=1024")
# create a signing request for this file
machine.succeed(
"openssl ts -query -data data.raw -cert -sha256 -no_nonce -out request.tsq"
)
# offer it to the signing server
machine.succeed(
"curl --cacert ${tsWebRoot}/keys/ca.pem -H Content-type:application/timestamp-query --data-binary @request.tsq https://tts.local/timestamp > reply.tsq"
)
# dump the content of the reply.
#
machine.succeed("openssl ts -reply -text -in reply.tsq")
# verify that it is actually signed & valid - and matches the hash of our file
#
machine.succeed(
"openssl ts -verify -in reply.tsq -data data.raw -CAfile ${tsWebRoot}/keys/fullchain-ts-service.pem"
)
# In this simple, cannonical case - we can also check straight against the CA - as there
# is nothing in between.
#
machine.succeed(
"openssl ts -verify -in reply.tsq -data data.raw -CAfile ${tsWebRoot}/keys/ca.pem"
)
'';
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment