more text, inclding actual reasons you shouldn't use it

This commit is contained in:
Daniel Barlow 2024-09-29 10:20:10 +01:00
parent a56a9ba013
commit 0844177d51
1 changed files with 38 additions and 19 deletions

View File

@ -1,27 +1,27 @@
# Certifix
Not an Asterix character. A small HTTP(S)[*] API that accepts X509
CSRs and signs them if they contain the magic number (specifically, if
they have a custom `challengePassword` attribute containing a
pre-agreed value)
Not an Asterix character.
Modelled on the Puppet CA "Policy-based autosigning" functionality,
but without the rest of Puppet
A small HTTPS API modelled on the description of the
[Puppet CA "Policy-based autosigning" functionality](
https://www.puppet.com/docs/puppet/7/ssl_attributes_extensions#csr_custom_attributes-recommended-oids-custom-attributes),
that accepts X509 CSRs and automatically signs them without human
interaction if they have a custom `challengePassword` attribute
containing a pre-agreed value.
What's it for? I have a bunch of small devices on my LAN that may or
may not be able to retain persistent state across reboots. I would
like them to be able to talk securely to a server using standard TLS
with client authentication, and without having to rely on network
firewall rules to prevent the rest of the world also talking to the
service.
[*] it will do S, but as of writing this footnote it doesn't yet
like them to be able to talk securely to services on the network using
standard TLS with client authentication, and (because "[zero trust]
(https://en.wikipedia.org/wiki/Zero_trust_security_model)")
without having to rely on network firewall rules to prevent the rest
of the world also being able to talk to the service.
## To try it out
_This is experiment-quality code that I have published mostly so that
it does't die with my laptop. Some day it will be grown-up but in the
meantime try it at your own risk - or even better, don't try it_
_This is alpha-quality code which was written by someone with only the
most passing familiarity with TLS or cryptography in general, and
has not been audited. Try it at your own risk._
It's written in [Fennel](https://www.fennel-lang.org). To build it
either use Nix or read [package.nix](package.nix) and figure out how
@ -38,7 +38,7 @@ chmod 0700 psk
openssl genrsa -out ca.key 4096
CN=CA openssl req -config openssl.cnf -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt
# create key for the server and sign it with the CA
# create key for the server and sign it with the CA
CN=localhost openssl req -config openssl.cnf -newkey rsa:2048 -nodes -keyout server.key --out server.csr
openssl x509 -req -in server.csr -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
@ -46,14 +46,33 @@ openssl x509 -req -in server.csr -days 365 -CA ca.crt -CAkey ca.key -CAcreateser
CN=rotuer openssl req -config openssl.cnf -newkey rsa:2048 -nodes -keyout client.key -out client.csr
# build and start the server
nix-build && result/bin/certifix --challenge-password psk --certificate ca.crt --private-key ca.key localhost:19613
nix-build && result/bin/certifix --challenge-password psk --ca-certificate ca.crt --ca-private-key --server-certificate server.crt --server-private-key server.key localhost:19613
# send it
curl -v -H 'content-type: application/x-pem-file' --data-binary @client.csr https://localhost:19613/sign
```
## Reasons this is not secure
* the CA key is present in the memory of the process that reads and
parses network requests
* there is no "intermediate" key: requests are signed by the root key
* I haven't checked that the protocols or the ciphers are restricted
to modern and sensible defaults
* doesn't set 4.2.1.6. Subject Alternative Name
* doesn't set Key Usage extension (https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3)
* likewise other TLS best practices
## Background
* [how Puppet does it](https://www.puppet.com/docs/puppet/7/ssl_attributes_extensions#csr_custom_attributes-recommended-oids-custom-attributes)
* [RFC 5967 - spec for a CSR](https://datatracker.ietf.org/doc/html/rfc5967)