docs: add BIND TSIG guide and align project documentation
Create bind-tsig-configuration.md for allow-update and allow-transfer setup. Link from README and project spec; extend .gitignore for .env files. Record implementation decisions for change C-00001-setup-project. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -23,7 +23,7 @@ Follow `docs/project-specification.md` for design and implementation.
|
|||||||
- Domain names: **ASCII only** in v1
|
- Domain names: **ASCII only** in v1
|
||||||
- UPDATE: **automatic TCP fallback** on UDP truncation
|
- UPDATE: **automatic TCP fallback** on UDP truncation
|
||||||
- Integration tests: **BIND testcontainer** (`go test -tags=integration ./...`)
|
- Integration tests: **BIND testcontainer** (`go test -tags=integration ./...`)
|
||||||
- **`docs/bind-tsig-configuration.md`** — BIND `allow-update` / `allow-transfer` guide (implementation phase)
|
- **`docs/bind-tsig-configuration.md`** — BIND `allow-update` / `allow-transfer` guide
|
||||||
- Typed **zone data structures** (`Record`, `Zone`, etc.) for transfer/update results
|
- Typed **zone data structures** (`Record`, `Zone`, etc.) for transfer/update results
|
||||||
- Project `.cursor` overrides workspace rules for this module
|
- Project `.cursor` overrides workspace rules for this module
|
||||||
|
|
||||||
|
|||||||
@@ -24,3 +24,5 @@ coverage.html
|
|||||||
|
|
||||||
# Local config (secrets)
|
# Local config (secrets)
|
||||||
testconfig/local.toml
|
testconfig/local.toml
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
|||||||
@@ -21,5 +21,6 @@ Module path: `gitea.neitzel.de/konrad/go-dns` — import as **`godns`**.
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [Project specification](docs/project-specification.md)
|
- [Project specification](docs/project-specification.md)
|
||||||
|
- [BIND TSIG configuration](docs/bind-tsig-configuration.md)
|
||||||
- [Product backlog](docs/backlog.md)
|
- [Product backlog](docs/backlog.md)
|
||||||
- [Change efforts](docs/changes/)
|
- [Change efforts](docs/changes/)
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
# BIND TSIG configuration for go-dns
|
||||||
|
|
||||||
|
This guide describes how to configure **BIND 9** so a **TSIG shared secret** can perform:
|
||||||
|
|
||||||
|
- **Dynamic updates** (RFC 2136) — the same operations as `nsupdate`
|
||||||
|
- **Full zone transfer (AXFR)** — read the entire zone over TCP
|
||||||
|
|
||||||
|
The **go-dns** library (`godns`) signs requests with TSIG; BIND verifies the signature and applies ACLs for that key. **Key generation is not part of go-dns** — operators create keys with BIND tooling or copy secrets from existing secret management.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- BIND 9.x authoritative server for the target zone
|
||||||
|
- Shell access to edit `named.conf` (or included snippets) and reload the server
|
||||||
|
- A TSIG key name, algorithm, and Base64 secret (see [Define the TSIG key](#define-the-tsig-key))
|
||||||
|
|
||||||
|
## Define the TSIG key
|
||||||
|
|
||||||
|
Generate a key on the server (or any host with BIND utilities):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tsig-keygen -a hmac-sha256 go-dns-key
|
||||||
|
```
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rndc tsig-keygen -a hmac-sha256 go-dns-key
|
||||||
|
```
|
||||||
|
|
||||||
|
Output is a `key { ... };` block suitable for `named.conf`. Example:
|
||||||
|
|
||||||
|
```bind
|
||||||
|
key "go-dns-key" {
|
||||||
|
algorithm hmac-sha256;
|
||||||
|
secret "q4f6j2+8vK9mN3pR7sT1uW5xY0zA2bC4dE6fG8hI0jK=";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Place the key in `named.conf` or in an included file (e.g. `/etc/bind/keys.conf`) referenced with:
|
||||||
|
|
||||||
|
```bind
|
||||||
|
include "/etc/bind/keys.conf";
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important:** Treat the secret like a password. Do not commit it to version control. go-dns callers pass the same key name, algorithm, and secret at runtime.
|
||||||
|
|
||||||
|
## Configure the zone
|
||||||
|
|
||||||
|
Reference the key in the zone block for the origin you want to update and transfer. Both ACLs are required for go-dns clients that perform updates and AXFR with the same key:
|
||||||
|
|
||||||
|
```bind
|
||||||
|
zone "example.com" {
|
||||||
|
type master;
|
||||||
|
file "/var/lib/bind/db.example.com";
|
||||||
|
allow-update { key "go-dns-key"; };
|
||||||
|
allow-transfer { key "go-dns-key"; };
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
| Directive | Purpose |
|
||||||
|
|-----------|---------|
|
||||||
|
| `allow-update` | Permits RFC 2136 UPDATE messages signed with this TSIG key |
|
||||||
|
| `allow-transfer` | Permits AXFR (full zone transfer) to clients signing with this TSIG key |
|
||||||
|
|
||||||
|
If you only need updates or only transfers, grant the corresponding directive alone. go-dns supports separate keys per client instance when policy requires different read and write credentials.
|
||||||
|
|
||||||
|
## Optional: stricter update policy
|
||||||
|
|
||||||
|
Broad `allow-update { key "..."; };` grants update access to the entire zone. For finer control, use **`update-policy`** instead of or in addition to `allow-update`:
|
||||||
|
|
||||||
|
```bind
|
||||||
|
zone "example.com" {
|
||||||
|
type master;
|
||||||
|
file "/var/lib/bind/db.example.com";
|
||||||
|
allow-transfer { key "go-dns-key"; };
|
||||||
|
update-policy {
|
||||||
|
grant go-dns-key subdomain example.com. A AAAA TXT;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Policy syntax and grant types are documented in the BIND 9 Administrator Reference Manual. Choose `allow-update` or `update-policy` according to your security model; do not leave zones open to unauthenticated updates.
|
||||||
|
|
||||||
|
## Reload and validate configuration
|
||||||
|
|
||||||
|
1. Check syntax:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
named-checkconf
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Reload BIND (adjust command for your installation):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rndc reload
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verify **dynamic update** (replace host, zone, and key values):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nsupdate -y hmac-sha256:go-dns-key:BASE64SECRET <<EOF
|
||||||
|
server ns.example.com
|
||||||
|
zone example.com
|
||||||
|
update add test.example.com 300 IN A 192.0.2.10
|
||||||
|
send
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Verify **AXFR** with TSIG:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dig @ns.example.com example.com AXFR -y hmac-sha256:go-dns-key:BASE64SECRET +tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
A successful transfer lists all zone records and terminates with the zone's SOA RR.
|
||||||
|
|
||||||
|
## Security notes
|
||||||
|
|
||||||
|
- **Restrict scope** — Grant the key only on zones that automation must manage. Avoid `allow-update { key ...; };` on parent zones unless intentional.
|
||||||
|
- **Do not expose AXFR publicly** — Zone transfers reveal full zone contents. Restrict `allow-transfer` to trusted networks or TSIG keys; never use `allow-transfer { any; };` on the Internet.
|
||||||
|
- **Separate read and write keys** — Use one TSIG key with `allow-transfer` only and another with `allow-update` only when policy requires split privileges. go-dns clients configure one key per session.
|
||||||
|
- **Rotate secrets** — When rotating a TSIG secret, update BIND and all go-dns callers together; mismatched secrets produce `BADSIG` errors.
|
||||||
|
- **Algorithm choice** — Prefer **hmac-sha256** (or stronger) over legacy hmac-md5 for new keys.
|
||||||
|
|
||||||
|
## Complete minimal example
|
||||||
|
|
||||||
|
The following fragment is a self-contained illustration (adjust paths and zone data file):
|
||||||
|
|
||||||
|
```bind
|
||||||
|
key "go-dns-key" {
|
||||||
|
algorithm hmac-sha256;
|
||||||
|
secret "q4f6j2+8vK9mN3pR7sT1uW5xY0zA2bC4dE6fG8hI0jK=";
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "example.com" {
|
||||||
|
type master;
|
||||||
|
file "/var/lib/bind/db.example.com";
|
||||||
|
allow-update { key "go-dns-key"; };
|
||||||
|
allow-transfer { key "go-dns-key"; };
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Ensure `db.example.com` exists with a valid SOA and NS records before loading the zone.
|
||||||
|
|
||||||
|
## Related documentation
|
||||||
|
|
||||||
|
- [Project specification](project-specification.md) — library scope, TSIG model, AXFR-only transfers
|
||||||
|
- [Change 00001 spec](changes/00001-setup-project/spec.md) — full DNS operation catalog and BIND guide requirements
|
||||||
|
- [Product backlog](backlog.md) — future work (e.g. IXFR)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Implementation decisions: Initial project setup and DNS operation catalog
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
- **Change folder:** `docs/changes/00001-setup-project/`
|
||||||
|
- **Branch:** `feature/C-00001-setup-project`
|
||||||
|
- **Scope:** Documentation and scaffolding only (no Go source)
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
| # | Area | Decision | Rationale |
|
||||||
|
|---|------|----------|-----------|
|
||||||
|
| 1 | Git baseline | Baseline commit pushed before implementation edits | Per `implement-change` skill and plan step 0 |
|
||||||
|
| 2 | BIND guide | Single `docs/bind-tsig-configuration.md` with all spec section 9 topics | Primary deliverable of this change |
|
||||||
|
| 3 | Example secret | Placeholder Base64 in guide (not a real key) | Illustration only; guide warns against committing secrets |
|
||||||
|
| 4 | `.gitignore` | Added `.env` and `.env.*` | Spec requirement 10; was missing from specify phase |
|
||||||
|
| 5 | Library code | No `doc.go` or placeholder `godns` package | Plan explicitly excludes `*.go`; first API change adds packages |
|
||||||
|
|
||||||
|
## Deviations from plan
|
||||||
|
|
||||||
|
- None.
|
||||||
|
|
||||||
|
## Follow-ups / risks
|
||||||
|
|
||||||
|
- **`go work sync` at workspace root** may fail if sibling module `log-analyzer` lacks `go.mod` (pre-existing workspace issue). AC-1 verification should use `go-dns/go.mod` directly or fix workspace separately.
|
||||||
|
- **Gitea repo** was available; baseline and feature branch push succeeded.
|
||||||
|
- **verify-agent:** Run full AC-1 through AC-10 checklist from `plan.md`.
|
||||||
|
- **Next change:** Implement `package godns` wire protocol (RFC 2136 UPDATE, AXFR, TSIG) per backlog/spec.
|
||||||
|
|
||||||
|
## Files touched
|
||||||
|
|
||||||
|
| Path | Action |
|
||||||
|
|------|--------|
|
||||||
|
| `docs/bind-tsig-configuration.md` | created |
|
||||||
|
| `docs/project-specification.md` | modified — live BIND guide links |
|
||||||
|
| `README.md` | modified — BIND guide link |
|
||||||
|
| `.gitignore` | modified — `.env` patterns |
|
||||||
|
| `.cursor/rules/project-specification.mdc` | modified — guide path wording |
|
||||||
|
| `docs/changes/00001-setup-project/impl-decisions.md` | created |
|
||||||
|
|
||||||
|
Git: `git init`, remote `origin`, branch `feature/C-00001-setup-project`, baseline commit `47f1744`.
|
||||||
@@ -37,7 +37,7 @@ The authoritative list lives in change **00001-setup-project** ([spec.md](change
|
|||||||
2. **Dynamic update** — add, delete, prerequisites, batch UPDATE; typed RR builders
|
2. **Dynamic update** — add, delete, prerequisites, batch UPDATE; typed RR builders
|
||||||
3. **Zone transfer** — **AXFR** only; parse stream into zone data
|
3. **Zone transfer** — **AXFR** only; parse stream into zone data
|
||||||
4. **Zone data model** — `Record`, `RRSet`, `Zone`, `UpdateResult`, `TransferResult`
|
4. **Zone data model** — `Record`, `RRSet`, `Zone`, `UpdateResult`, `TransferResult`
|
||||||
5. **BIND guide** — `docs/bind-tsig-configuration.md` (how to set `allow-update` + `allow-transfer` for a key)
|
5. **BIND guide** — [bind-tsig-configuration.md](bind-tsig-configuration.md) (`allow-update` + `allow-transfer` for a TSIG key)
|
||||||
|
|
||||||
Future work: [backlog.md](backlog.md) (includes **IXFR**).
|
Future work: [backlog.md](backlog.md) (includes **IXFR**).
|
||||||
|
|
||||||
@@ -58,7 +58,9 @@ Future work: [backlog.md](backlog.md) (includes **IXFR**).
|
|||||||
|
|
||||||
## BIND configuration
|
## BIND configuration
|
||||||
|
|
||||||
Operators configure BIND so a TSIG key may **update** and **transfer** a zone (`allow-update`, `allow-transfer`). Requirements and example are in the change spec; the standalone guide will live at **`docs/bind-tsig-configuration.md`** (written during implementation).
|
Operators configure BIND so a TSIG key may **update** and **transfer** a zone (`allow-update`, `allow-transfer`). Step-by-step instructions, security notes, and a minimal `named.conf` example:
|
||||||
|
|
||||||
|
**[docs/bind-tsig-configuration.md](bind-tsig-configuration.md)**
|
||||||
|
|
||||||
## Change workflow
|
## Change workflow
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user