ACME development

Standards

Testing

Test using certbot

The project includes a specialized Docker Compose override file so that you can start django-ca using docker compose and then use a container to use certbot.

If you want to test the current development state, you must first locally build the image:

$ DOCKER_BUILDKIT=1 docker build -t mathiasertl/django-ca:latest .

Then start the setup with the override file and you’ll get a complete setup and a certbot container that can be used to retrieve certificates. The DNS of setup so that the CA can be reached at ca.example.com:

$ export COMPOSE_FILE=docker-compose.yml:ca/django_ca/tests/fixtures/docker-compose.certbot.yaml
$ docker compose up -d
...
$ docker compose exec backend manage createsuperuser
...
$ docker compose exec backend manage init_ca \
>     --path-length=1 --subject-format=rfc4514 Root CN=Root
$ docker compose exec backend manage init_ca --path-length=0 --path=ca/shared/ \
>     --parent=Root --acme-enable --subject-format=rfc4514 Intermediate CN=Intermediate

After that, you can login to the web interface at http://localhost/admin/ to view progress.

You can now start a shell in the certbot container and request a certificate. Note that certbot is preconfigured to use the django-ca registry in the container next to it:

$ docker compose exec certbot /bin/bash
root@certbot:~# certbot register
root@certbot:~# django-ca-test-validation.sh http http-01.example.com
root@certbot:~# django-ca-test-validation.sh dns dns-01.example.com

Use certbot directly

You can use certbot with a server started via manage.py runserver to test issuing certificates for localhost:

# certbot register --agree-tos -m user@localhost \
>    --config-dir=.certbot/config/ --work-dir=.certbot/work/ --logs-dir=.certbot/logs \
>    --server http://localhost:8000/django_ca/acme/directory/

# certbot certonly --standalone \
>    --config-dir=.certbot/config/ --work-dir=.certbot/work/ --logs-dir=.certbot/logs \
>    --server http://localhost:8000/django_ca/acme/directory/ \
>    -d localhost

You can revoke a certificate:

# certbot revoke \
>     --config-dir=.certbot/config/ --work-dir=.certbot/work/ --logs-dir=.certbot/logs \
>     --server http://localhost:8000/django_ca/acme/directory/ \
>     --cert-name localhost

Use a different configuration/work directory if you “lost your account key”:

# certbot revoke \
>     --config-dir=.certbot1/config/ --work-dir=.certbot1/work/ --logs-dir=.certbot1/logs \
>     --server http://localhost:8000/django_ca/acme/directory/ \
>     --key-path .certbot/config/archive/localhost/privkey1.pem \
>     --cert-path .certbot/config/archive/localhost/fullchain1.pem \
>     --reason keycompromise

Tips and tricks

Query LE:

$ curl -v https://acme-v02.api.letsencrypt.org/directory

base64url encoding

ACMEv2 uses the Base 64 Encoding with URL and Filename Safe Alphabet encoding for binary data. This is similar but not identical to standard base64 encoding.

The ACME library does that with josepy (which is not the similar/forked? python-jose):

>>> import josepy as jose
>>> jose.b64encode(b'test')
b'dGVzdA'
>>> jose.b64decode(b'dGVzdA')
b'test'