Commit 587d41ea authored by Adrien Dorsaz's avatar Adrien Dorsaz
Browse files

move wiki pages to /documentations

parent a745e655
......@@ -41,9 +41,9 @@ but they do fantastic work.
## How to use this script
See the [HowTo Use](https://projects.adorsaz.ch/adrien/acme-dns-tiny/wikis/howto-use) wiki page for main informations.
See the [HowTo Use](./documentations/howto-use.md) documentation page for main informations.
You may be interested by the [HowTo Setup with BIND9](https://projects.adorsaz.ch/adrien/acme-dns-tiny/wikis/howto-setup-with-bind9)
You may be interested by the [HowTo Setup with BIND9](./documentations/howto-setup-with-bind9.md)
page too which show a step by step example to set up the script
with a BIND9 DNS server.
......
# Example acme-dns-tiny setup with BIND9 DNS server
Below, you'll find example of a setup of an environment to get a certificate with Let's Encrypt servers.
## System settings to run the script on a secure machine
*Note*: the acme_dns_tiny.py script *don't need* to be run on the same machine than the DNS server.
* Create specific user for the script
```
root ~ $ adduser --home /opt/acme-dns/ --disabled-password acme-dns
```
* Login as this user and clone acme-dns-tiny
```
root ~ $ su - acme-dns
```
* Change umask to create by default non-readable files and repository by others
```
acme-dns ~ $ echo "umask 027" >> ~/.profile && umask 027
acme-dns ~ $ git clone https://projects.adorsaz.ch/adrien/acme-dns-tiny.git
```
* Create a directory which will contain account keys, certificate signature requests, ...
```
acme-dns ~ $ mkdir -p letsencrypt/account/ letsencrypt/csr/
acme-dns ~ $ chmod -R o-rwx letsencrypt
```
* If your system knows POSIX ACL, force all new created files in this directory to be unreadable by «other»
```
acme-dns ~ $ setfacl -Rm "default:other:---" letsencrypt
```
## BIND9 TSIG key creation on the DNS server
You should read the BIND9 Administrator Reference Manual to have a complete documentation about TSIG and dynamic updates.
> Update (November 2020): the steps described bellow to create a TSIG key are working, but are not the official way.
>
> I keep them because that's really the way I did to set up my server.
>
> The bind9 admin documentation [explains](https://bind9.readthedocs.io/en/v9_16_7/advanced.html#generating-a-shared-key) you should use instead the command `tsig-keygen host1-host2. > host1-host2.key` to create the shared TSIG key file.
Here are steps I've done to set up the adorsaz.ch server:
```
root ~ $ umask 027
root ~ $ mkdir tsig && cd tsig
root ~/tsig/ $ dnssec-keygen -a hmac-sha256 -b 128 -n HOST adorsaz.ch-acmedns.
```
* Give BIND9 access to the both key files
```
root ~/tsig/ $ chown root:bind9 -R . # or use POSIX ACL: setfacl -Rm "user:bind9:r-x" .
```
Then, modify your bind9 configuration to add TSIG keys:
```
key "adorsaz.ch-acmedns."{
algorithm hmac-sha256;
secret "SECRET_FOUND_IN_KEY_FILE==";
};
```
Finally, you have to modify your zone configuration to add a DNS dynamic update policies for this key.
The key need to be able to modify TXT ressource records corresponding to the domain name to be verified prefixed by `_acme-challenge.`.
For example, to verify domains `adorsaz.ch` and `www.adorsaz.ch` with the same key:
```
update-policy {
grant adorsaz.ch-acmedns. name _acme-challenge.adorsaz.ch. TXT;
grant adorsaz.ch-acmedns. name _acme-challenge.www.adorsaz.ch. TXT;
};
```
## Finish setup on first machine
* Create ACME account key
```
acme-dns ~ $ cd letsencrypt/account/
acme-dns ~/letsencrypt/account/ $ openssl genrsa 4096 > adorsaz.key
```
* Create domain key and certificate request
```
root ~ $ umask 027
root ~ $ openssl genrsa 4096 > adorsaz.domain.key
root ~ $ openssl req -new -sha256 -key adorsaz.domain.key -subj "/CN=adorsaz.ch" > adorsaz.csr # See the general "How to use" page for multiple domains request
root ~ $ cp adorsaz.csr ~acme-dns/letsencrypt/csr/
root ~ $ chown root:acme-dns ~acme-dns/letsencrypt/csr/adorsaz.csr
```
* Configure acme-dns-tiny with all above collected informations
```
acme-dns ~/letsencrypt/csr/ $ cd ~/acme-dns-tiny
acme-dns ~/acme-dns-tiny $ cp example.ini adorsaz.ini
```
Edit the new ini file with correspondent configuration in each section.
You have to copy TSIG informations from key file generated on the DNS server (use a secure way to copy them).
Keep the `ACMEDirectory` with *staging* Let's Encrypt url for your tests.
## Test and run !
Run the python script with your configuration (see [How to use](./howto-use.m.mdd))
If some errors occur, read them carefully: python exceptions may give you enough details to fix your setup (file permissions, configuration errors, ...).
When you got your first certificate with the staging server, then you are ready to use the production server.
Edit your configuration file to set up the `CAUrl` setting to the production servers of Let's Encrypt.
Finally, re-run the script and you'll get your first real certificate !
# How to use acme-dns-tiny project
If you already have a Let's Encrypt issued certificate and just want to renew,
you should only have to do Steps 3 and 6.
### Step 1: Create a Let's Encrypt account private key (if you haven't already)
This step need to be done on the machine which will run the `acme-dns-tiny` script.
You must have a public key registered with Let's Encrypt and sign your requests
with the corresponding private key. If you don't understand what I just said,
this script likely isn't for you! Please use the official Let's Encrypt
[client](https://github.com/letsencrypt/letsencrypt).
To accomplish this you need to initially create a key, that can be used by
`acme-dns-tiny`, to register an account for you and sign all following requests.
NOTE: currently, `acme-dns-tiny` expects the account key to be a RSA key, as the original `acme-tiny`.
It seems that the external contributor drdaeman [has been able to update the original script](https://github.com/drdaeman/acme-tiny/commit/f995b09b67498ef6fc538867eeeb63643cba5702) to be able to detect
automatically ECDSA account key.
```
openssl genrsa 4096 > account.key
```
#### Use existing Let's Encrypt key
Alternatively you can convert your key, previously generated by the original
Let's Encrypt client.
The private account key from the Let's Encrypt client is saved in the
[JWK](https://tools.ietf.org/html/rfc7517) format. `acme-dns-tiny` is using the PEM
key format. To convert the key, you can use the tool
[conversion script](https://gist.github.com/JonLundy/f25c99ee0770e19dc595)
by JonLundy:
```sh
# Download the script
curl 'https://gist.githubusercontent.com/JonLundy/f25c99ee0770e19dc595/raw/6035c1c8938fae85810de6aad1ecf6e2db663e26/conv.py' > conv.py
# Copy your private key to your working directory
cp /etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/<id>/private_key.json private_key.json
# Create a DER encoded private key
openssl asn1parse -noout -out private_key.der -genconf <(python conv.py private_key.json)
# Convert to PEM
openssl rsa -in private_key.der -inform der > account.key
```
### Step 2: Create a certificate signing request (CSR) for your domains.
This step need to be done on the server running TLS services.
The ACME protocol (what Let's Encrypt uses) requires a CSR file to be submitted
to it, even for renewals. You can use the same CSR for multiple renewals.
NOTE: you can't use your account private key as your domain private key!
Let's encrypt has support for both RSA and ECDSA (ECC) certificates. Depending on your
needs and if you don't have a private key already, you can generate a new key with one
of the following command:
```
# Generate a 384-bit ECDSA domain private key (to get an ECC certificate)
openssl ecparam -out domain.key -name secp384r1 -genkey
# Or generate a RSA domain private key
openssl genrsa 4096 > domain.key
```
Then, you can generate the Certificate Signing Request (CSR), using one of the following commands:
```
# If you want to sign a single domain
openssl req -new -sha256 -key domain.key -subj "/CN=example.org" > domain.csr
# If multiple domains should be signed and your OpenSSL version is >= 1.1.1
# (use this one if you want both www.example.org and example.org)
openssl req -new -sha256 -key domain.key -subj "/" -addext "subjectAltName = DNS:example.org, DNS:www.example.org" > domain.csr
# If multiple domains should be signed and your OpenSSL version is < 1.1.1
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.org,DNS:www.example.org")) > domain.csr
```
Finally, copy the CSR (yes, only the CSR without the key) on the machine which will run the `acme-dns-tiny` script.
### Step 3: Make your DNS server allows dynamic updates
You must prove you own the domains you want a certificate for, so Let's Encrypt
requires you host some specific DNS resource records during the signing process.
When you'll ask to verify the domain `example.com`, ACME protocol requires your DNS
server to host a TXT resource record to the domain `_acme-challenge.example.com`
with a specific identifier as value (if you ask to verify multiple domains, you'll have to
create for each domain a record prefixed by `_acme-challenge`).
The `acme-dns-tiny` script will generate and write those DNS records to your
DNS server by use of DNS dynamic message updates.
So you have to configure your DNS server to allow dynamic DNS
updates and create a TSIG key which will give rights to perform updates on TXT
records for every domain prefixed by `_acme-challenge`.
If you use BIND9 as DNS server, you can read the step by step example on [the bind9 setup how to](./howto-setup-with-bind9.md)
The configuration of the script will need:
* the TSIG key name and value
* the algorithm used for TSIG key (hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 or hmac-512; list of algoithm depends on [known ones](http://www.dnspython.org/docs/1.14.0/dns.tsig-module.html#_hashes) by dnspython module)
* the DNS zone to update
* the address and the port of the DNS server
### Step 4: Configure the script
This step need to be done on the machine which will run the `acme-dns-tiny` script.
The simplest way to configure the script is to copy the `example.ini` file
from this repository.
**Be careful! Set read permissions correctly on the configuration file, because
it will contain the key authorized to modify your DNS configuration !**
Then update the configuration file with path to the account key, the CSR, the TSIG
informations, your DNS configurations.
Note, as DNS update may won't be applied instantly we apply a default delay
of 10 seconds between the DNS update and the self-validation of DNS record.
You can modify/suppress this delay by updating the `TTL` setting to correspond to
your DNS server configuration (keep in mind the "self-validation" will wait up to `10 * TTL`
seconds before giving up).
Note, the `example.ini` contains by default the *staging* Let's Encrypt server
URL. When you'll be ready, you'll need to set up the `ACMEDirectory` with the production
URL of your CA. For example, the Let's Encrypt CA production URL is
`https://acme-v02.api.letsencrypt.org/directory`.
### Step 5: Get a signed certificate!
This step need to be done on the machine which will run the `acme-dns-tiny` script.
Now that you have setup your DNS server, generated all the needed files and configured
the `acme-dns-tiny` script, you can run this script on a computer containing your
private account key, the CSR and the configuration (it *doesn't need* to be run on your
production server directly).
```
python3 acme_dns_tiny.py example.ini > ./chain.pem
```
If every thing was ok, `chain.pem` contains your signed certificate followed by the
CA's certificate which signed yours.
### Step 6: Install the certificate
The certificate chain that is output by this script can be used along
with your private domain key to run any service on your server which need TSL encryption.
You need to include both file in the TLS settings of your services.
So you have to copy the chain file from your machine which have run the `acme-dns-tiny` script$
to your server running TLS services.
### Step 7: Setup an auto-renew cronjob
Congrats! Your server is now using TLS!
Unfortunately, Let's Encrypt certificates only last for 90 days, so you need to
renew them often. No worries! It can be automated !
Just make a bash script and add it to your crontab (see below for an _example_, you may prefer another script language ;)).
Example of a skeleton for `renew_cert.sh` script:
```sh
#!/bin/bash
# Configuration
## You should use another directory as /tmp could be destroyed regularly
WORKINGDIR="/tmp/acme-dns-tiny"
# Notes about this script
## You should also add code to create backup of older certificates
## You may need code to handle HPKP (key pining in HTTP) updates
## You may need to update DANE (key pining in DNS) too
## With HPKP and DANE, you should also consider your automatic key rollover
## which will need to update the CSR file and/or your DNS DANE records.
# Pre run script: configure a secure workspace using ACL POSIX
mkdir -p "${WORKINGDIR}"
setfacl -m "default:other:--- , other:---" "${WORKINGDIR}"
# Run the script
python3 /path/to/acme_dns_tiny.py domain.ini > "${WORKINGDIR}/chain.pem" || exit
# Post run script
## Here, you should give access to your TLS services to the chain.pem file
## (maybe by sending it to the server running the TLS services or move to a location readable
## by these services if the script is on the same machine)
## and reload/restart each service using TLS
```
Then you'll need to configure a cron job to execute this script regularly.
If you use systemd, you can create a "one shot" systemd service and a systemd timer to run it.
For the cron/timer configuration, you should consider:
* Certificates issued by Let's Encrypt servers are currently valid for 3 months, so set the timer a bit shorter.
* To avoid DDOS on CA servers, set random minutes (and/or day in the month) to run the script
* systemd allow to run this script with a non-privileged user service and chain it with a privileged service which
will restart TLS based services.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment