modified: README.md
modified: certbot_dns_netbox/dns_netbox.py
This commit is contained in:
1 parent
93248447b2
commit
da48d8ef90
2 files changed
+131
-20
No files matched your search
@@ -20,23 +20,6 @@ and the plugin **never creates or deletes records**:
|
||||
3. leaves the records in place after validation so they can be updated again
|
||||
on the next renewal.
|
||||
|
||||
### Provisioning
|
||||
|
||||
The challenge TXT records must be created beforehand in netbox-dns, in the
|
||||
view configured via `search_view` (`certbot_dns_netbox/dns_netbox.py`,
|
||||
default: `global`). Each challenge token needs its own record:
|
||||
|
||||
| Certificate request | TXT records needed |
|
||||
| ------------------------------------------------------ | ------------------ |
|
||||
| `-d example.com` or `-d '*.example.com'` | 1 |
|
||||
| `-d example.com -d '*.example.com'` (apex + wildcard) | 2 |
|
||||
|
||||
All records for a challenge share the same name (e.g. name
|
||||
`_acme-challenge.unifi` in zone `ewcs.ch`); netbox-dns allows multiple TXT
|
||||
records with different values for the same name. If a certificate request
|
||||
needs more records than exist, certbot aborts with an error. Renewals simply
|
||||
rewrite the values, so the records never need to be touched again.
|
||||
|
||||
Connection settings are taken from the environment, exactly as `nbapi.py`
|
||||
expects them:
|
||||
|
||||
@@ -51,12 +34,140 @@ One of `NETBOX_BEARER` / `NETBOX_TOKEN` is required. The token's user needs
|
||||
NetBox object permissions to view and change netbox-dns records only — no
|
||||
zone or view permissions are required.
|
||||
|
||||
## Tutorial: end-to-end setup
|
||||
|
||||
This walkthrough sets up certificates for `example.com`, including the
|
||||
wildcard, from scratch. Adapt domains, names and paths to your environment.
|
||||
|
||||
### 1. Create the DNS zone
|
||||
|
||||
Create the `example.com` zone in netbox-dns, in the view the plugin searches
|
||||
(`search_view` in `certbot_dns_netbox/dns_netbox.py`, default: `_default_`), and
|
||||
note the numeric **zone ID** of the new zone — it is shown in the web UI URL
|
||||
and can be looked up with:
|
||||
|
||||
```
|
||||
GET /api/plugins/netbox-dns/zones/?name=example.com
|
||||
```
|
||||
|
||||
### 2. Create a NetBox permission
|
||||
|
||||
In the NetBox admin interface, create a permission named
|
||||
`ACME Client - Zone example.com`:
|
||||
|
||||
* **Object type**: `DNS › record` only
|
||||
* **Actions**: view and change — nothing else. The plugin never creates or
|
||||
deletes records, and it does not need zone or view permissions.
|
||||
* **Constraint**:
|
||||
|
||||
```json
|
||||
{"name": "_acme-challenge", "type": "TXT", "zone_id": 0000}
|
||||
```
|
||||
|
||||
`0000` is the zone ID from step 1. The constraint limits the token to TXT
|
||||
records named `_acme-challenge` in exactly that zone. Note that certificates
|
||||
for sub-domains (`-d sub.example.com`) use a record named
|
||||
`_acme-challenge.sub`; in that case, relax the constraint to
|
||||
`"name__startswith": "_acme-challenge"` instead of the exact `name`.
|
||||
|
||||
### 3. Create a service user
|
||||
|
||||
* Create a user group, e.g. `ACME Clients`, and assign the permission from
|
||||
step 2 to the **group** — any service user added to the group later
|
||||
inherits it.
|
||||
* Create a user, e.g. `certbot`, without a usable login, and make it a member
|
||||
of the group.
|
||||
|
||||
### 4. Pre-provision the TXT records
|
||||
|
||||
The plugin only updates records, so they must exist before the first run.
|
||||
Create `_acme-challenge` TXT records in the `example.com` zone — one per
|
||||
challenge token:
|
||||
|
||||
| Certificate request | TXT records needed |
|
||||
| ----------------------------------------------------- | ------------------ |
|
||||
| `-d example.com` or `-d '*.example.com'` | 1 |
|
||||
| `-d example.com -d '*.example.com'` (apex + wildcard) | 2 |
|
||||
|
||||
All records for a challenge share the same name (`_acme-challenge`, relative
|
||||
to the zone); netbox-dns allows multiple TXT records with different values
|
||||
for the same name. Initial values are placeholders and get rewritten by the
|
||||
plugin. If a certificate request needs more records than exist, certbot
|
||||
aborts with `Not enough TXT records ...` — add another record and rerun.
|
||||
|
||||
### 5. Create an API token and environment file
|
||||
|
||||
On the `certbot` user, create an API token (leave write enabled) and expose
|
||||
it to whatever runs certbot — a cronjob in most cases — via environment
|
||||
variables. Keep them in a root-readable-only file, e.g.
|
||||
`/etc/default/certbot-netbox`:
|
||||
|
||||
```sh
|
||||
NETBOX_URL=https://netbox.example.com
|
||||
NETBOX_TOKEN=<token> # or: NETBOX_BEARER=<token>
|
||||
```
|
||||
|
||||
```
|
||||
chmod 600 /etc/default/certbot-netbox
|
||||
```
|
||||
|
||||
### 6. Install certbot and the plugin in a dedicated venv
|
||||
|
||||
Do not install certbot from the system package manager — certbot and the
|
||||
plugin live together in a dedicated venv:
|
||||
|
||||
```sh
|
||||
python3 -m venv /opt/certbot-netbox
|
||||
/opt/certbot-netbox/bin/pip install certbot certbot-dns-netbox
|
||||
```
|
||||
|
||||
### 7. Test
|
||||
|
||||
```sh
|
||||
/opt/certbot-netbox/bin/certbot certonly \
|
||||
--authenticator dns-netbox \
|
||||
-d example.com -d '*.example.com'
|
||||
```
|
||||
|
||||
The first ever certbot run asks for an ACME account e-mail and the terms of
|
||||
service. During the run the plugin writes the challenge tokens into the
|
||||
`_acme-challenge` TXT records; the records remain in place afterwards. Tip:
|
||||
append `--dry-run` for a first try to validate the setup against the staging
|
||||
ACME API without touching rate limits.
|
||||
|
||||
### 8. Automate renewal
|
||||
|
||||
Create a wrapper that loads the environment and runs certbot from the venv,
|
||||
e.g. `/usr/local/bin/certbot-netbox-renew`:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
set -a
|
||||
. /etc/default/certbot-netbox
|
||||
set +a
|
||||
exec /opt/certbot-netbox/bin/certbot renew --quiet
|
||||
```
|
||||
|
||||
```
|
||||
chmod +x /usr/local/bin/certbot-netbox-renew
|
||||
```
|
||||
|
||||
And a cron entry, e.g. `/etc/cron.d/certbot-netbox`:
|
||||
|
||||
```
|
||||
0 3 * * * root /usr/local/bin/certbot-netbox-renew >> /var/log/certbot-netbox-renew.log 2>&1
|
||||
```
|
||||
|
||||
`certbot renew` reads the renewal configuration written by step 7, so no
|
||||
authenticator flags are needed here. Add a `--deploy-hook` (e.g. restarting
|
||||
the web server) if services need to pick up the renewed certificate.
|
||||
|
||||
## Installation
|
||||
|
||||
Install into the same Python environment as certbot:
|
||||
|
||||
```
|
||||
pip install ./certbot-dns-netbox
|
||||
pip install certbot-dns-netbox
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -107,6 +218,6 @@ certbot certonly --dry-run \
|
||||
-d sub.example.com # end-to-end against the staging ACME API
|
||||
```
|
||||
|
||||
Watch the `_acme-challenge` TXT records in the `global` view: their values
|
||||
Watch the `_acme-challenge` TXT records in the `_default_` view: their values
|
||||
change to the challenge tokens during the run and remain in place afterwards.
|
||||
The next renewal updates the same records again.
|
||||
@@ -26,7 +26,7 @@ from certbot.plugins import dns_common
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# netbox-dns view that contains the zone with the challenge TXT record.
|
||||
search_view = "global"
|
||||
search_view = "_default_"
|
||||
|
||||
|
||||
class Authenticator(dns_common.DNSAuthenticator):
|
||||
|
||||
Reference in new issue
Block a user