ACME to ZeroSSL.com REST API, based on acme2certifier.
This server will enable normal ACME clients to issue certificates from non-acme servers, the main goal is to issue certificates from ZeroSSL (via REST API) for normal ACME clients. This will enable us to have ZeroSSL account key under one place, instead of distributing it to all clients.
Because ACME and ZeroSSL.com require domain verification, a custom setup need to be set with a name server (name.com API).
Certificates will be issued for sub-domains under a configured main domain, A CA handler is implemented for acme2certifier in zerossl_ca_handler.py, where it tries to issue certificates from ZeroSSL via rest API.
The full flow is as follows:
- Clients (e.g certbot) sends a request to the ACME server
- The custom CA handler with the ACME server will:
- Take the client's CSR and creates a new certificate.
- Register the DNS challenge returned from the previous step in
cname_validation_p1andcname_validation_p2fields as aCNAMErecord. - Ask ZeroSSL to verify the domains, and waits for the result.
- If the verification is done, it will wait for the certificate to be issued for sometime, by polling the certificate information and checking for the
status. - If the certificate is issued successfully, it will be returned to the user.
1 - Name server: zerossl.com needs to verify domains, we need access to name server where we can register required DNS records.
The following options are available for now:
- name.com
2 - This ACME server configured with:
- Current domains and prefixes
- name.com client configurations
- ZeroSSL access key
python3 -m pip install virtualenv --user
python3 -m virtualenv .venv
source .venv/bin/activate
pip install -r requirements.txt
Then run this only once:
python django_update.py
Server is configured by acme_srv.cfg configuration file in the acme directory, before starting, check current example files at config directory, you can copy any of them:
cp config/acme_srv.zerossl.cfg acme/acme_srv.cfgThen update it with correct configuration and start the development server as:
python manage.py runserverTo configure the ACME server with ZeroSSL handler, acme_srv.cfg need to be placed into acme directory with the the following sections:
[CAhandler]
# CA specific options
handler_file: zerossl_ca_handler.py
cert_validity_days: 90
access_key: <zerossl api access key>
[domains]
grid.tf: test1, test2
3bots.tf: testnet, devnet
gateway.tf: gw1, gw2, gw3
[namecom]
username: foo
token: bar
[redis]
host: localhost
port: 6379
Sections:
domains(required): allowed domains and prefixes (hosts) (comma separated).- For example,
grid.tf: test1, test2will allow issuing certificate for subdomains oftest1.grid.tfandtest2.grid.tf, e.g.a.test1.grid.tf,xyz.test2.grid.tf.
- For example,
namecom(required): name.com API credentialsredis(optional): redis redis configuration for caching of prefetched certs
namecom must be configured in order to verify domains for now. Note that the IP of the server must be whitelisted in at name.com side to use the configured credentials.
If dev flag is used with namecom, it will use development api endpoints.
See acme_srv_zerossl.cf for full configuration example.
First, you need to have a django settings.py for production, it should be configured with other databases than sqlite in DATABASES, e.g. mysql. Also ALLOWED_HOSTS need to include all possible hosts.
To use a production settings module in e.g. acme2certifier/production_settings.py, just set it in DJANGO_SETTINGS_MODULE like:
export DJANGO_SETTINGS_MODULE=acme2certifier.production_settings
It's better to use gunicorn to run the server for production environments, with other options, you just need to pass the wsgi app as:
source .venv/bin/activate # activate the environment first
gunicorn acme2certifier.wsgi #...other optionsAlso, gunicorn should run behind nginx, see deploying gunicorn for more details about the setup and configuration.
We will try to create a full docker setup for this server, database engine and redis.
You need to make sure to pass --server pointing to the current ACME server address, for example to get the certificate only from a local setup, where the server is running on 127.0.0.1:8000
certbot certonly --server http://127.0.0.1:8000/ --standalone -d tt.example.com --cert-name tt --agree-tos -m abdo@gmail.com
Nearly all code is from acme2certifier repository, with acme implementation with django database store (db_handler) + django server and scripts, all in one place for the ease of development/experimenting.
- Copied django db_handler.py inside acme as
db_handler. - Renamed the django app module acme to be
appinn all relevant places to avoid import conflicts with acme implementation module. - Updated settings.py of django app to work with sqlite database instead of mysql.
- Generated keys and certificates to run the openssl ca handler at acme_ca and added the configuration for it in example configuration at acme_srv.local_ssl.cfg.
- Used virtualenv and generated
requirements.txtto be easier to install and run the server without complex setup.
