diff --git a/.bind9version b/.bind9version new file mode 100644 index 0000000..d5c45db --- /dev/null +++ b/.bind9version @@ -0,0 +1,43 @@ +# BIND9 9.18 LTS Support Branch + +Branch: 9.18 +Purpose: Long-term support for BIND9 9.18.x (ISC LTS release) +Status: Active +Support Level: Full + +## Version Information + +- **BIND9 Version**: 9.18.x (LTS) +- **Supported Until**: Aligned with ISC BIND9 9.18 LTS support timeline +- **Branch Base**: BIND9 9.18.44 (as of February 2026) + +## Supported Platforms + +- Debian 11 (Bullseye) +- Debian 12 (Bookworm) +- Debian 13 (Trixie) +- Ubuntu 20.04 LTS +- Ubuntu 22.04 LTS +- Ubuntu 24.04 LTS + +## Policies + +### Backporting +- ✅ Security fixes: Always backported +- ✅ Bug fixes: Backported if compatible +- ❌ New features: Case-by-case (no breaking changes) +- ❌ Breaking changes: Never + +### Release Numbering +Uses MAJOR.MINOR.PATCH (e.g., v1.2.3) + +## Key Documentation + +- [Version Support Policy](docs/VERSION_SUPPORT.md) +- [Configuration Grammar](CONFIGURATION_GRAMMAR.md) +- [Changelog](CHANGELOG.md) +- [README](README.md) + +## Next Major Version + +For BIND9 9.20+ support, see the `main` branch which will eventually have version-specific releases. diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index ef09de8..8cc0aa6 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -54,8 +54,8 @@ jobs: run: | pip install --no-cache-dir \ ansible \ - molecule[podman] \ - podman-compose \ + molecule \ + molecule-podman \ pyyaml \ jinja2 diff --git a/AGENTS.md b/AGENTS.md index 693c81c..a4c866b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,3 +4,41 @@ Ensure that all practices and instructions described by https://raw.githubusercontent.com/ansible/ansible-creator/refs/heads/main/docs/agents.md are followed. + +## Repository Actions + +**Use gitea-mcp tools for all repository interactions.** Do not use `curl`, `git`, or direct API calls. + +### When to Use gitea-mcp + +- Fetching issues, PRs, branches, tags, releases +- Reading files, directories, or commits from repo +- Creating issues, PRs, comments, tags, or releases +- Editing issues or PRs + +### Wrong vs Right + +❌ `curl http://git.valid.dk/api/v1/repos/daniel/ansible-bind9-role/issues/6` + +✅ `mcp_gitea-mcp_list_repo_issues(owner, repo, page, pageSize)` + +### Local Workspace + +Terminal commands are fine for: +- Compiling, testing, building +- Git operations on local files (commit, push) +- Using `read_file`, `grep_search`, `semantic_search` + +## General project workflow +1. Check for open tickets +2. Choose next logical ticket to work on +3. Create branch for ticket +4. Create plan for ticket +5. Execute plan +6. Create appropriate commits to repository +7. Submit PR to repository +8. Review the PR critically +9. Check if further work is needed to resolve the issues found +10. Loop 8-9 until complete +11. Ask me to review the PR and merge it +12. Close the ticket \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6a823a8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,120 @@ +# Changelog + +All notable changes to the ansible-bind9-role will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Version support policy documentation in `docs/VERSION_SUPPORT.md` +- Branching strategy for supporting multiple BIND9 versions +- Grammar comparison tooling (`scripts/compare_bind_versions.py`) +- Grammar fetcher for upstream BIND9 sources (`scripts/fetch_bind_grammar.py`) +- Automated version difference tracking +- Operating system support matrix +- BIND9 Version Differences documentation (`docs/BIND_VERSION_DIFFERENCES.md`) covering: + - 44 breaking changes between BIND9 9.18.44 and 9.20.18 + - 35 new options in BIND9 9.20 + - 22 modified options requiring configuration updates + - 3 newly deprecated options + +### Changed +- Established formal release management process +- Defined backporting policy for security, bugs, and features +- Clarified version compatibility in CONFIGURATION_GRAMMAR.md + +### Planned +- BIND9 9.20+ support in separate `9.20` branch +- Multi-platform molecule test matrix +- Automated BIND9 version detection in tasks +- Version-specific template conditional logic +- Enhanced CI/CD pipeline with version matrix testing + +## [1.0.0] - TBD + +### Initial Release +- Full support for BIND9 9.18.x (LTS) +- Configuration grammar based on BIND9 9.18.44 +- Comprehensive template system for all BIND9 statement types: + - `acl` + - `controls` + - `dlz` + - `dnssec-policy` + - `dyndb` + - `http` + - `key` + - `logging` + - `options` + - `parental-agents` + - `primaries` (masters) + - `server` + - `statistics-channels` + - `tls` + - `trust-anchors` + - `view` + - `zone` (all types: primary, secondary, forward, hint, stub, static-stub, mirror, redirect, in-view, delegation-only) +- Support for Debian 11, 12, 13 +- Support for Ubuntu 20.04, 22.04, 24.04 +- Molecule testing framework +- Configuration validation with `named-checkconf` +- Automatic configuration backup and rollback on errors +- Detailed configuration grammar documentation +- GPL-3.0-or-later license + +--- + +## Version History (Pre-Changelog) + +Prior to this changelog, the role was developed without formal version tracking. +This changelog starts with the establishment of the version support policy. + +--- + +## Versioning Schema + +- **MAJOR**: Incompatible changes to role variables or behavior +- **MINOR**: New features in a backwards compatible manner +- **PATCH**: Backwards compatible bug fixes + +### Branch-Specific Versioning + +- `main` branch: `vX.Y.Z` (BIND9 9.18 LTS) +- `9.20` branch: `v9.20.X[-suffix]` (BIND9 9.20+) + - Suffixes: `-alpha`, `-beta`, `-rc` for pre-releases + +## Release Types + +### Security Releases +Critical security fixes are released as patch versions and backported to all supported branches. + +### Feature Releases +New features are added in minor version increments. Breaking changes require major version increments. + +### Bug Fix Releases +Bug fixes are released as patch versions when they accumulate or for critical issues. + +## Upgrade Notes + +### From Pre-Versioned to v1.0.0 +The first official release establishes baseline compatibility. Users of pre-release versions should: +1. Review all role variables for any changes +2. Test in non-production environment +3. Review generated configuration with `named-checkconf` +4. Check `docs/VERSION_SUPPORT.md` for supported platforms + +### Future Upgrades +Check individual version sections above for specific upgrade notes and breaking changes. + +## Contributing + +See `docs/VERSION_SUPPORT.md` for contribution guidelines and release processes. + +## Links + +- [Version Support Policy](docs/VERSION_SUPPORT.md) +- [Configuration Grammar](CONFIGURATION_GRAMMAR.md) +- [Issue Tracker](https://git.valid.dk/daniel/ansible-bind9-role/issues) +- [Repository](https://git.valid.dk/daniel/ansible-bind9-role) + diff --git a/CONFIGURATION_GRAMMAR.md b/CONFIGURATION_GRAMMAR.md index 211a80f..4ea40b5 100644 --- a/CONFIGURATION_GRAMMAR.md +++ b/CONFIGURATION_GRAMMAR.md @@ -39,6 +39,17 @@ The BIND9 role uses YAML to replicate the official ISC BIND9 configuration forma - `max-cache-ttl` → `max_cache_ttl` - `dnssec-policy` → `dnssec_policy` +### Version Compatibility + +This role and its configuration grammar are based on **BIND9 9.18.x (LTS)**. + +For information about upgrading to BIND9 9.20 or later, see [BIND9 Version Differences](docs/BIND_VERSION_DIFFERENCES.md) which documents: +- **Breaking changes** between versions +- **New features** available in newer versions +- **Migration guidance** for configuration updates + +⚠️ **Important:** BIND9 9.20 introduces significant breaking changes. Please review the version differences document before upgrading configurations. + ## Configuration Structure All configuration is defined through four precedence-based variables that are merged: diff --git a/README.md b/README.md index 9491dee..6f5aa78 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,20 @@ bind9 ===== -A feature-complete ansible role for installing and configuring bind9. The purpose of this role is to fully template out the entire official bind9 configuration file format. +A feature-complete ansible role for installing and configuring bind9. The purpose of this role is to fully template out the entire official bind9 configuration file format. + +## Version Compatibility + +| BIND9 Version | Role Branch | Status | Supported Platforms | +|---------------|-------------|--------|---------------------| +| 9.18.x (LTS) | `main` | ✅ Supported | Debian 11-13, Ubuntu 20.04-24.04 | +| 9.20.x+ | `9.20` | 🚧 Planned | Debian 12-13, Ubuntu 22.04-24.04 | + +For detailed version support policy, branching strategy, and migration guidance, see [docs/VERSION_SUPPORT.md](docs/VERSION_SUPPORT.md). + +**Minimum Requirements:** +- Ansible: 2.13+ +- Python: 3.8+ What the role does: - Fully configures named.conf @@ -195,10 +208,30 @@ Simple sample config of a recursive BIND server that allows your localnetwork to allow-recursion: - mylan +## Documentation + +- **[Configuration Grammar Reference](CONFIGURATION_GRAMMAR.md)**: Comprehensive guide to all BIND9 configuration options +- **[Version Support Policy](docs/VERSION_SUPPORT.md)**: Supported versions, branching strategy, and release management +- **[Changelog](CHANGELOG.md)**: Version history and upgrade notes + +## Contributing + +Contributions are welcome! Please see [docs/VERSION_SUPPORT.md](docs/VERSION_SUPPORT.md) for: +- Branching strategy +- Testing requirements +- Backporting policies +- Release procedures + +## Links + +- **Repository**: https://git.valid.dk/daniel/ansible-bind9-role +- **Issues**: https://git.valid.dk/daniel/ansible-bind9-role/issues +- **BIND9 Documentation**: https://bind9.readthedocs.io/ + License ------- -BSD +GPL-3.0-or-later Author Information ------------------ diff --git a/bind9-grammar/upstream/README.md b/bind9-grammar/upstream/README.md new file mode 100644 index 0000000..14ae913 --- /dev/null +++ b/bind9-grammar/upstream/README.md @@ -0,0 +1,54 @@ +# BIND9 Grammar Files - Upstream Source + +This directory contains upstream BIND9 grammar files from the official BIND9 mirror for version comparison and validation. + +## Files to Fetch + +When grammar files are needed, fetch from: +- **Repository**: https://git.valid.dk/Mirrors/bind9 +- **9.18 Tag**: v9.18.44 +- **9.20 Tag**: v9.20.18 + +### Required Grammar Files (from doc/misc/) + +- options +- forward.zoneopt +- hint.zoneopt +- in-view.zoneopt +- mirror.zoneopt +- primary.zoneopt +- redirect.zoneopt +- secondary.zoneopt +- static-stub.zoneopt +- stub.zoneopt +- delegation-only.zoneopt +- rndc.grammar +- parsegrammar.py +- checkgrammar.py + +## Directory Structure + +``` +upstream/ +├── v9.18.44/ +│ ├── grammar/ (Grammar files) +│ └── metadata.json (Fetch metadata) +└── v9.20.18/ + ├── grammar/ (Grammar files) + └── metadata.json (Fetch metadata) +``` + +## Fetching + +Option 1: Using git fetch +```bash +git clone --depth 1 --branch v9.18.44 https://git.valid.dk/Mirrors/bind9.git /tmp/bind9-9.18 +cp /tmp/bind9-9.18/doc/misc/* bind9-grammar/upstream/v9.18.44/grammar/ +``` + +Option 2: Using Gitea MCP tools (see scripts/fetch_bind_grammar.py) + +## Scripts + +- `scripts/fetch_bind_grammar.py` - MCP-based fetcher template +- `scripts/compare_bind_versions.py` - Grammar comparison tool diff --git a/bind9-grammar/upstream/v9.18.44/grammar/delegation-only.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/delegation-only.zoneopt new file mode 100644 index 0000000..ab86327 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/delegation-only.zoneopt @@ -0,0 +1,3 @@ +zone [ ] { + type delegation-only; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/forward.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/forward.zoneopt new file mode 100644 index 0000000..069f2ce --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/forward.zoneopt @@ -0,0 +1,6 @@ +zone [ ] { + type forward; + delegation-only ; // deprecated + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/hint.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/hint.zoneopt new file mode 100644 index 0000000..d14c3ef --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/hint.zoneopt @@ -0,0 +1,6 @@ +zone [ ] { + type hint; + check-names ( fail | warn | ignore ); + delegation-only ; // deprecated + file ; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/in-view.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/in-view.zoneopt new file mode 100644 index 0000000..c63c427 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/in-view.zoneopt @@ -0,0 +1,3 @@ +zone [ ] { + in-view ; +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/mirror.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/mirror.zoneopt new file mode 100644 index 0000000..5f688ca --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/mirror.zoneopt @@ -0,0 +1,45 @@ +zone [ ] { + type mirror; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + check-names ( fail | warn | ignore ); + database ; + file ; + ixfr-from-differences ; + journal ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + use-alt-transfer-source ; // deprecated + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/options b/bind9-grammar/upstream/v9.18.44/grammar/options new file mode 100644 index 0000000..871d6ad --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/options @@ -0,0 +1,604 @@ +acl { ; ... }; // may occur multiple times + +controls { + inet ( | | * ) [ port ( | * ) ] allow { ; ... } [ keys { ; ... } ] [ read-only ]; // may occur multiple times + unix perm owner group [ keys { ; ... } ] [ read-only ]; // may occur multiple times +}; // may occur multiple times + +dlz { + database ; + search ; +}; // may occur multiple times + +dnssec-policy { + dnskey-ttl ; + keys { ( csk | ksk | zsk ) [ ( key-directory ) ] lifetime algorithm [ ]; ... }; + max-zone-ttl ; + nsec3param [ iterations ] [ optout ] [ salt-length ]; + parent-ds-ttl ; + parent-propagation-delay ; + parent-registration-delay ; // obsolete + publish-safety ; + purge-keys ; + retire-safety ; + signatures-jitter ; + signatures-refresh ; + signatures-validity ; + signatures-validity-dnskey ; + zone-propagation-delay ; +}; // may occur multiple times + +dyndb { }; // may occur multiple times + +http { + endpoints { ; ... }; + listener-clients ; + streams-per-connection ; +}; // may occur multiple times + +key { + algorithm ; + secret ; +}; // may occur multiple times + +logging { + category { ; ... }; // may occur multiple times + channel { + buffered ; + file [ versions ( unlimited | ) ] [ size ] [ suffix ( increment | timestamp ) ]; + null; + print-category ; + print-severity ; + print-time ( iso8601 | iso8601-utc | local | ); + severity ; + stderr; + syslog [ ]; + }; // may occur multiple times +}; + +managed-keys { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times, deprecated + +options { + allow-new-zones ; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + answer-cookie ; + attach-cache ; + auth-nxdomain ; + auto-dnssec ( allow | maintain | off ) ; // deprecated + automatic-interface-scan ; + avoid-v4-udp-ports { ; ... }; // deprecated + avoid-v6-udp-ports { ; ... }; // deprecated + bindkeys-file ; + blackhole { ; ... }; + catalog-zones { zone [ default-primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-wildcard ; + clients-per-query ; + cookie-algorithm ( aes | siphash24 ); + cookie-secret ; // may occur multiple times + coresize ( default | unlimited | ); // deprecated + datasize ( default | unlimited | ); // deprecated + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + directory ; + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; + dnsrps-enable ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dnstap-identity ( | none | hostname ); // not configured + dnstap-output ( file | unix ) [ size ( unlimited | ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; // not configured + dnstap-version ( | none ); // not configured + dscp ; // obsolete + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dump-file ; + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + files ( default | unlimited | ); // deprecated + flush-zones-on-shutdown ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + fstrm-set-buffer-hint ; // not configured + fstrm-set-flush-timeout ; // not configured + fstrm-set-input-queue-size ; // not configured + fstrm-set-output-notify-threshold ; // not configured + fstrm-set-output-queue-model ( mpscs | spscs ); // not configured + fstrm-set-output-queue-size ; // not configured + fstrm-set-reopen-interval ; // not configured + geoip-directory ( | none ); + glue-cache ; // deprecated + heartbeat-interval ; // deprecated + hostname ( | none ); + http-listener-clients ; + http-port ; + http-streams-per-connection ; + https-port ; + interface-interval ; + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + keep-response-order { ; ... }; + key-directory ; + lame-ttl ; + listen-on [ port ] [ tls ] [ http ] { ; ... }; // may occur multiple times + listen-on-v6 [ port ] [ tls ] [ http ] { ; ... }; // may occur multiple times + lmdb-mapsize ; + lock-file ( | none ); + managed-keys-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-mapped-addresses ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-rsa-exponent-size ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + maxz-zone-ttl ( unlimited | ); + memstatistics ; + memstatistics-file ; + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-rate ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + pid-file ( | none ); + port ; + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + querylog ; + random-device ( | none ); // obsolete + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recurse-ing-file ; + recursion ; + recursive-clients ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + reserved-sockets ; // deprecated + resolver-nonbackoff-tries ; // deprecated + resolver-query-timeout ; + resolver-retry-interval ; // deprecated + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + reuse port ; + root-delegation-only [ exclude { ; ... } ]; // deprecated + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + secroots-file ; + send-cookie ; + serial-query-rate ; + serial-update-method ( date | increment | unixtime ); + server-id ( | none | hostname ); + servfail-ttl ; + session-keyalg ; + session-keyfile ( | none ); + session-keyname ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + sortlist { ; ... }; + stacksize ( default | unlimited | ); // deprecated + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + startup-notify-rate ; + statistics-file ; + suppress-initial-notify ; // obsolete + synth-from-dnssec ; + tcp-advertised-timeout ; + tcp-clients ; + tcp-idle-timeout ; + tcp-initial-timeout ; + tcp-keepalive-timeout ; + tcp-listen-queue ; + tcp-receive-buffer ; + tcp-send-buffer ; + tkey-dhkey ; // deprecated + tkey-domain ; // deprecated + tkey-gssapi-credential ; // deprecated + tkey-gssapi-keytab ; + tls-port ; + transfer-format ( many-answers | one-answer ); + transfer-message-size ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers-in ; + transfers-out ; + transfers-per-ns ; + trust-anchor-telemetry ; + try-tcp-refresh ; + udp-receive-buffer ; + udp-send-buffer ; + update-check-ksk ; + update-quota ; + use-alt-transfer-source ; // deprecated + use-v4-udp-ports { ; ... }; // deprecated + use-v6-udp-ports { ; ... }; // deprecated + v6-bias ; + validate-except { ; ... }; + version ( | none ); + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; + +parental-agents [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times + +plugin ( query ) [ { } ]; // may occur multiple times + +primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times + +server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; +}; // may occur multiple times + +statistics-channels { + inet ( | | * ) [ port ( | * ) ] [ allow { ; ... } ]; // may occur multiple times +}; // may occur multiple times + +tls { + ca-file ; + cert-file ; + ciphers ; + dhparam-file ; + key-file ; + prefer-server-ciphers ; + protocols { ; ... }; + remote-hostname ; + session-tickets ; +}; // may occur multiple times + +trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + +trusted-keys { ; ... }; // may occur multiple times, deprecated + +view [ ] { + allow-new-zones ; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + attach-cache ; + auth-nxdomain ; + auto-dnssec ( allow | maintain | off ) ; // deprecated + catalog-zones { zone [ default-primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-wildcard ; + clients-per-query ; + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dlz { + database ; + search ; + }; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; + dnsrps-enable ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dyndb { }; // may occur multiple times + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + glue-cache ; // deprecated + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + key { + algorithm ; + secret ; + }; // may occur multiple times + key-directory ; + lame-ttl ; + lmdb-mapsize ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-clients { ; ... }; + match-destinations { ; ... }; + match-recursive-only ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + maxz-zone-ttl ( unlimited | ); + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + plugin ( query ) [ { } ]; // may occur multiple times + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recursion ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + resolver-nonbackoff-tries ; // deprecated + resolver-query-timeout ; + resolver-retry-interval ; // deprecated + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + root-delegation-only [ exclude { ; ... } ]; // deprecated + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + send-cookie ; + serial-update-method ( date | increment | unixtime ); + server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; + }; // may occur multiple times + servfail-ttl ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + sortlist { ; ... }; + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + suppress-initial-notify ; // obsolete + synth-from-dnssec ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + trust-anchor-telemetry ; + trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + trusted-keys { ; ... }; // may occur multiple times, deprecated + try-tcp-refresh ; + update-check-ksk ; + use-alt-transfer-source ; // deprecated + v6-bias ; + validate-except { ; ... }; + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.18.44/grammar/primary.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/primary.zoneopt new file mode 100644 index 0000000..6b54f0c --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/primary.zoneopt @@ -0,0 +1,64 @@ +zone [ ] { + type primary; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + auto-dnssec ( allow | maintain | off ) ; // deprecated + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( fail | warn | ignore ); + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-wildcard ; + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); + file ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-transfer-idle-out ; + max-transfer-time-out ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + serial-update-method ( date | increment | unixtime ); + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + update-check-ksk ; + update-policy ( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesubject ) [ ] ; ... } ); + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/redirect.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/redirect.zoneopt new file mode 100644 index 0000000..9d238c1 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/redirect.zoneopt @@ -0,0 +1,15 @@ +zone [ ] { + type redirect; + allow-query { ; ... }; + allow-query-on { ; ... }; + dlz ; + file ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/rndc.grammar b/bind9-grammar/upstream/v9.18.44/grammar/rndc.grammar new file mode 100644 index 0000000..f28ec73 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/rndc.grammar @@ -0,0 +1,20 @@ +key { + algorithm ; + secret ; +}; // may occur multiple times + +options { + default-key ; + default-port ; + default-server ; + default-source-address ( | * ); + default-source-address-v6 ( | * ); +}; + +server { + addresses { ( [ port ] | [ port ] | [ port ] ); ... }; + key ; + port ; + source-address ( | * ); + source-address-v6 ( | * ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.18.44/grammar/secondary.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/secondary.zoneopt new file mode 100644 index 0000000..19fae5a --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/secondary.zoneopt @@ -0,0 +1,67 @@ +zone [ ] { + type secondary; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + alt-transfer-source ( | * ) ; // deprecated + alt-transfer-source-v6 ( | * ) ; // deprecated + auto-dnssec ( allow | maintain | off ) ; // deprecated + check-names ( fail | warn | ignore ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; + dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-update-mode ( maintain | no-resign ); + file ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + update-check-ksk ; + use-alt-transfer-source ; // deprecated + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/static-stub.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/static-stub.zoneopt new file mode 100644 index 0000000..93a3220 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/static-stub.zoneopt @@ -0,0 +1,13 @@ +zone [ ] { + type static-stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + max-records ; + max-records-per-type ; + max-types-per-name ; + server-addresses { ( | ); ... }; + server-names { ; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.18.44/grammar/stub.zoneopt b/bind9-grammar/upstream/v9.18.44/grammar/stub.zoneopt new file mode 100644 index 0000000..2834682 --- /dev/null +++ b/bind9-grammar/upstream/v9.18.44/grammar/stub.zoneopt @@ -0,0 +1,29 @@ +zone [ ] { + type stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + check-names ( fail | warn | ignore ); + database ; + delegation-only ; // deprecated + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + file ; + forward ( first | only ); + forwarders [ port ] { ( | ) [ port ]; ... }; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-time-in ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + multi-master ; + primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + use-alt-transfer-source ; // deprecated + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/forward.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/forward.zoneopt new file mode 100644 index 0000000..a0d26b1 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/forward.zoneopt @@ -0,0 +1,5 @@ +zone [ ] { + type forward; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/hint.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/hint.zoneopt new file mode 100644 index 0000000..2d2c98d --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/hint.zoneopt @@ -0,0 +1,5 @@ +zone [ ] { + type hint; + check-names ( fail | warn | ignore ); + file ; +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/in-view.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/in-view.zoneopt new file mode 100644 index 0000000..c63c427 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/in-view.zoneopt @@ -0,0 +1,3 @@ +zone [ ] { + in-view ; +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/mirror.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/mirror.zoneopt new file mode 100644 index 0000000..2e491cc --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/mirror.zoneopt @@ -0,0 +1,44 @@ +zone [ ] { + type mirror; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + check-names ( fail | warn | ignore ); + database ; + file ; + ixfr-from-differences ; + journal ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/options b/bind9-grammar/upstream/v9.20.18/grammar/options new file mode 100644 index 0000000..44ae262 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/options @@ -0,0 +1,605 @@ +acl { ; ... }; // may occur multiple times + +controls { + inet ( | | * ) [ port ( | * ) ] allow { ; ... } [ keys { ; ... } ] [ read-only ]; // may occur multiple times + unix perm owner group [ keys { ; ... } ] [ read-only ]; // may occur multiple times +}; // may occur multiple times + +dlz { + database ; + search ; +}; // may occur multiple times + +dnssec-policy { + cdnskey ; + cds-digest-types { ; ... }; + dnskey-ttl ; + inline-signing ; + keys { ( csk | ksk | zsk ) [ key-directory | key-store ] lifetime algorithm [ tag-range ] [ ]; ... }; + manual-mode ; + max-zone-ttl ; + nsec3param [ iterations ] [ optout ] [ salt-length ]; + offline-ksk ; + parent-ds-ttl ; + parent-propagation-delay ; + publish-safety ; + purge-keys ; + retire-safety ; + signatures-jitter ; + signatures-refresh ; + signatures-validity ; + signatures-validity-dnskey ; + zone-propagation-delay ; +}; // may occur multiple times + +dyndb { }; // may occur multiple times + +http { + endpoints { ; ... }; + listener-clients ; + streams-per-connection ; +}; // may occur multiple times + +key { + algorithm ; + secret ; +}; // may occur multiple times + +key-store { + directory ; + pkcs11-uri ; +}; // may occur multiple times + +logging { + category { ; ... }; // may occur multiple times + channel { + buffered ; + file [ versions ( unlimited | ) ] [ size ] [ suffix ( increment | timestamp ) ]; + null; + print-category ; + print-severity ; + print-time ( iso8601 | iso8601-utc | local | ); + severity ; + stderr; + syslog [ ]; + }; // may occur multiple times +}; + +managed-keys { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times, deprecated + +options { + allow-new-zones ; + allow-notify { ; ... }; + allow-proxy { ; ... }; // experimental + allow-proxy-on { ; ... }; // experimental + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + answer-cookie ; + attach-cache ; + auth-nxdomain ; + automatic-interface-scan ; + avoid-v4-udp-ports { ; ... }; // deprecated + avoid-v6-udp-ports { ; ... }; // deprecated + bindkeys-file ; // test only + blackhole { ; ... }; + catalog-zones { zone [ default-primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-svcb ; + check-wildcard ; + clients-per-query ; + cookie-algorithm ( siphash24 ); + cookie-secret ; // may occur multiple times + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + directory ; + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; // obsolete + dnsrps-enable ; // not configured + dnsrps-library ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; // obsolete + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dnstap-identity ( | none | hostname ); // not configured + dnstap-output ( file | unix ) [ size ( unlimited | ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; // not configured + dnstap-version ( | none ); // not configured + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dump-file ; + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + flush-zones-on-shutdown ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + fstrm-set-buffer-hint ; // not configured + fstrm-set-flush-timeout ; // not configured + fstrm-set-input-queue-size ; // not configured + fstrm-set-output-notify-threshold ; // not configured + fstrm-set-output-queue-model ( mpscs | spscs ); // not configured + fstrm-set-output-queue-size ; // not configured + fstrm-set-reopen-interval ; // not configured + geoip-directory ( | none ); + hostname ( | none ); + http-listener-clients ; + http-port ; + http-streams-per-connection ; + https-port ; + interface-interval ; + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + key-directory ; + lame-ttl ; + listen-on [ port ] [ proxy ] [ tls ] [ http ] { ; ... }; // may occur multiple times + listen-on-v6 [ port ] [ proxy ] [ tls ] [ http ] { ; ... }; // may occur multiple times + lmdb-mapsize ; + managed-keys-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-mapped-addresses ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-rsa-exponent-size ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + max-validation-failures-per-fetch ; // experimental + max-validations-per-fetch ; // experimental + memstatistics ; + memstatistics-file ; + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-rate ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + pid-file ( | none ); + port ; + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * | none ); + query-source-v6 [ address ] ( | * | none ); + querylog ; + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recursing-file ; + recursion ; + recursive-clients ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + resolver-query-timeout ; + resolver-use-dns64 ; + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ servfail-until-ready ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + responselog ; + reuseport ; + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + secroots-file ; + send-cookie ; + serial-query-rate ; + serial-update-method ( date | increment | unixtime ); + server-id ( | none | hostname ); + servfail-ttl ; + session-keyalg ; + session-keyfile ( | none ); + session-keyname ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + sig0-checks-quota ; // experimental + sig0-checks-quota-exempt { ; ... }; // experimental + sig0-key-checks-limit ; + sig0-message-checks-limit ; + sortlist { ; ... }; // deprecated + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + startup-notify-rate ; + statistics-file ; + synth-from-dnssec ; + tcp-advertised-timeout ; + tcp-clients ; + tcp-idle-timeout ; + tcp-initial-timeout ; + tcp-keepalive-timeout ; + tcp-listen-queue ; + tcp-receive-buffer ; + tcp-send-buffer ; + tkey-domain ; // obsolete + tkey-gssapi-keytab ; + tls-port ; + transfer-format ( many-answers | one-answer ); + transfer-message-size ; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers-in ; + transfers-out ; + transfers-per-ns ; + trust-anchor-telemetry ; + try-tcp-refresh ; + udp-receive-buffer ; + udp-send-buffer ; + update-check-ksk ; // obsolete + update-quota ; + use-v4-udp-ports { ; ... }; // deprecated + use-v6-udp-ports { ; ... }; // deprecated + v6-bias ; + validate-except { ; ... }; + version ( | none ); + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; + +plugin ( query ) [ { } ]; // may occur multiple times + +remote-servers [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times + +server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + require-cookie ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; +}; // may occur multiple times + +statistics-channels { + inet ( | | * ) [ port ( | * ) ] [ allow { ; ... } ]; // may occur multiple times +}; // may occur multiple times + +tls { + ca-file ; + cert-file ; + cipher-suites ; + ciphers ; + dhparam-file ; + key-file ; + prefer-server-ciphers ; + protocols { ; ... }; + remote-hostname ; + session-tickets ; +}; // may occur multiple times + +trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + +trusted-keys { ; ... }; // may occur multiple times, deprecated + +view [ ] { + allow-new-zones ; + allow-notify { ; ... }; + allow-proxy { ; ... }; // experimental + allow-proxy-on { ; ... }; // experimental + allow-query { ; ... }; + allow-query-cache { ; ... }; + allow-query-cache-on { ; ... }; + allow-query-on { ; ... }; + allow-recursion { ; ... }; + allow-recursion-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + attach-cache ; + auth-nxdomain ; + catalog-zones { zone [ default-primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( primary | master | secondary | slave | response ) ( fail | warn | ignore ); // may occur multiple times + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-svcb ; + check-wildcard ; + clients-per-query ; + deny-answer-addresses { ; ... } [ except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... } ]; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + disable-algorithms { ; ... }; // may occur multiple times + disable-ds-digests { ; ... }; // may occur multiple times + disable-empty-zone ; // may occur multiple times + dlz { + database ; + search ; + }; // may occur multiple times + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; // may occur multiple times + dns64-contact ; + dns64-server ; + dnskey-sig-validity ; // obsolete + dnsrps-enable ; // not configured + dnsrps-options { }; // not configured + dnssec-accept-expired ; + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-must-be-secure ; // may occur multiple times, deprecated + dnssec-policy ; + dnssec-secure-to-insecure ; // obsolete + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + dnssec-validation ( yes | no | auto ); + dnstap { ( all | auth | client | forwarder | resolver | update ) [ ( query | response ) ]; ... }; // not configured + dual-stack-servers [ port ] { ( [ port ] | [ port ] | [ port ] ); ... }; + dyndb { }; // may occur multiple times + edns-udp-size ; + empty-contact ; + empty-server ; + empty-zones-enable ; + fetch-quota-params ; + fetches-per-server [ ( drop | fail ) ]; + fetches-per-zone [ ( drop | fail ) ]; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + ipv4only-contact ; + ipv4only-enable ; + ipv4only-server ; + ixfr-from-differences ( primary | master | secondary | slave | ); + key { + algorithm ; + secret ; + }; // may occur multiple times + key-directory ; + lame-ttl ; + lmdb-mapsize ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + match-clients { ; ... }; + match-destinations { ; ... }; + match-recursive-only ; + max-cache-size ( default | unlimited | | ); + max-cache-ttl ; + max-clients-per-query ; + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-ncache-ttl ; + max-query-count ; + max-query-restarts ; + max-records ; + max-records-per-type ; + max-recursion-depth ; + max-recursion-queries ; + max-refresh-time ; + max-retry-time ; + max-stale-ttl ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + max-udp-size ; + max-validation-failures-per-fetch ; // experimental + max-validations-per-fetch ; // experimental + message-compression ; + min-cache-ttl ; + min-ncache-ttl ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + minimal-any ; + minimal-responses ( no-auth | no-auth-recursive | ); + multi-master ; + new-zones-directory ; + no-case-compress { ; ... }; + nocookie-udp-size ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + nta-lifetime ; + nta-recheck ; + nxdomain-redirect ; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + plugin ( query ) [ { } ]; // may occur multiple times + preferred-glue ; + prefetch [ ]; + provide-ixfr ; + qname-minimization ( strict | relaxed | disabled | off ); + query-source [ address ] ( | * | none ); + query-source-v6 [ address ] ( | * | none ); + rate-limit { + all-per-second ; + errors-per-second ; + exempt-clients { ; ... }; + ipv4-prefix-length ; + ipv6-prefix-length ; + log-only ; + max-table-size ; + min-table-size ; + nodata-per-second ; + nxdomains-per-second ; + qps-scale ; + referrals-per-second ; + responses-per-second ; + slip ; + window ; + }; + recursion ; + request-expire ; + request-ixfr ; + request-nsid ; + require-server-cookie ; + resolver-query-timeout ; + resolver-use-dns64 ; + response-padding { ; ... } block-size ; + response-policy { zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]; ... } [ add-soa ] [ break-dnssec ] [ max-policy-ttl ] [ min-update-interval ] [ min-ns-dots ] [ nsip-wait-recurse ] [ nsdname-wait-recurse ] [ qname-wait-recurse ] [ recursive-only ] [ servfail-until-ready ] [ nsip-enable ] [ nsdname-enable ] [ dnsrps-enable ] [ dnsrps-options { } ]; + root-key-sentinel ; + rrset-order { [ class ] [ type ] [ name ] ; ... }; + send-cookie ; + serial-update-method ( date | increment | unixtime ); + server { + bogus ; + edns ; + edns-udp-size ; + edns-version ; + keys ; + max-udp-size ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + padding ; + provide-ixfr ; + query-source [ address ] ( | * ); + query-source-v6 [ address ] ( | * ); + request-expire ; + request-ixfr ; + request-nsid ; + require-cookie ; + send-cookie ; + tcp-keepalive ; + tcp-only ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + transfers ; + }; // may occur multiple times + servfail-ttl ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + sig0-key-checks-limit ; + sig0-message-checks-limit ; + sortlist { ; ... }; // deprecated + stale-answer-client-timeout ( disabled | off | ); + stale-answer-enable ; + stale-answer-ttl ; + stale-cache-enable ; + stale-refresh-time ; + synth-from-dnssec ; + transfer-format ( many-answers | one-answer ); + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + trust-anchor-telemetry ; + trust-anchors { ( static-key | initial-key | static-ds | initial-ds ) ; ... }; // may occur multiple times + trusted-keys { ; ... }; // may occur multiple times, deprecated + try-tcp-refresh ; + v6-bias ; + validate-except { ; ... }; + zero-no-soa-ttl ; + zero-no-soa-ttl-cache ; + zone-statistics ( full | terse | none | ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.20.18/grammar/primary.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/primary.zoneopt new file mode 100644 index 0000000..d4b1667 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/primary.zoneopt @@ -0,0 +1,63 @@ +zone [ ] { + type primary; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + check-dup-records ( fail | warn | ignore ); + check-integrity ; + check-mx ( fail | warn | ignore ); + check-mx-cname ( fail | warn | ignore ); + check-names ( fail | warn | ignore ); + check-sibling ; + check-spf ( warn | ignore ); + check-srv-cname ( fail | warn | ignore ); + check-svcb ; + check-wildcard ; + checkds ( explicit | ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; // obsolete + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-secure-to-insecure ; // obsolete + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + file ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-transfer-idle-out ; + max-transfer-time-out ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); // deprecated + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + serial-update-method ( date | increment | unixtime ); + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + update-policy ( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ ] ; ... } ); + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/redirect.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/redirect.zoneopt new file mode 100644 index 0000000..f457c80 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/redirect.zoneopt @@ -0,0 +1,15 @@ +zone [ ] { + type redirect; + allow-query { ; ... }; + allow-query-on { ; ... }; + dlz ; + file ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-types-per-name ; + max-zone-ttl ( unlimited | ); // deprecated + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/rndc.grammar b/bind9-grammar/upstream/v9.20.18/grammar/rndc.grammar new file mode 100644 index 0000000..f28ec73 --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/rndc.grammar @@ -0,0 +1,20 @@ +key { + algorithm ; + secret ; +}; // may occur multiple times + +options { + default-key ; + default-port ; + default-server ; + default-source-address ( | * ); + default-source-address-v6 ( | * ); +}; + +server { + addresses { ( [ port ] | [ port ] | [ port ] ); ... }; + key ; + port ; + source-address ( | * ); + source-address-v6 ( | * ); +}; // may occur multiple times diff --git a/bind9-grammar/upstream/v9.20.18/grammar/secondary.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/secondary.zoneopt new file mode 100644 index 0000000..2c07b9c --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/secondary.zoneopt @@ -0,0 +1,66 @@ +zone [ ] { + type secondary; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + check-names ( fail | warn | ignore ); + checkds ( explicit | ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + dlz ; + dnskey-sig-validity ; // obsolete + dnssec-dnskey-kskonly ; // obsolete + dnssec-loadkeys-interval ; + dnssec-policy ; + dnssec-update-mode ( maintain | no-resign ) ; // obsolete + file ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + inline-signing ; + ixfr-from-differences ; + journal ; + key-directory ; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-ixfr-ratio ( unlimited | ); + max-journal-size ( default | unlimited | ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + multi-master ; + notify ( explicit | master-only | primary-only | ); + notify-defer ; + notify-delay ; + notify-source ( | * ) ; + notify-source-v6 ( | * ) ; + notify-to-soa ; + nsec3-test-zone ; // test only + parental-agents [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-source ( | * ) ; + parental-source-v6 ( | * ) ; + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + request-expire ; + request-ixfr ; + sig-signing-nodes ; + sig-signing-signatures ; + sig-signing-type ; + sig-validity-interval [ ]; // obsolete + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + try-tcp-refresh ; + update-check-ksk ; // obsolete + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/static-stub.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/static-stub.zoneopt new file mode 100644 index 0000000..40a340f --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/static-stub.zoneopt @@ -0,0 +1,13 @@ +zone [ ] { + type static-stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + max-records ; + max-records-per-type ; + max-types-per-name ; + server-addresses { ( | ); ... }; + server-names { ; ... }; + zone-statistics ( full | terse | none | ); +}; diff --git a/bind9-grammar/upstream/v9.20.18/grammar/stub.zoneopt b/bind9-grammar/upstream/v9.20.18/grammar/stub.zoneopt new file mode 100644 index 0000000..abbc89d --- /dev/null +++ b/bind9-grammar/upstream/v9.20.18/grammar/stub.zoneopt @@ -0,0 +1,28 @@ +zone [ ] { + type stub; + allow-query { ; ... }; + allow-query-on { ; ... }; + check-names ( fail | warn | ignore ); + database ; + dialup ( notify | notify-passive | passive | refresh | ); // deprecated + file ; + forward ( first | only ); + forwarders [ port ] [ tls ] { ( | ) [ port ] [ tls ]; ... }; + masterfile-format ( raw | text ); + masterfile-style ( full | relative ); + max-records ; + max-records-per-type ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-time-in ; + max-types-per-name ; + min-refresh-time ; + min-retry-time ; + min-transfer-rate-in ; + multi-master ; + primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + transfer-source ( | * ) ; + transfer-source-v6 ( | * ) ; + zone-statistics ( full | terse | none | ); +}; diff --git a/defaults/main.yml b/defaults/main.yml index 34ba28d..a48cffc 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -16,7 +16,6 @@ bind9_config_indent: 4 bind9_group_config: [] bind9_site_config: [] bind9_host_config: [] - bind9_default_config: - name: named.conf backup: false @@ -28,10 +27,11 @@ bind9_default_config: options: directory: "{{ bind9_working_directory }}" -bind9_config: "{{ [bind9_default_config, - bind9_group_config, - bind9_site_config, - bind9_host_config] | - community.general.lists_mergeby('name', - recursive=true, - list_merge='append_rp') }}" +bind9_config: >- + {{ + [bind9_default_config, + bind9_group_config, + bind9_site_config, + bind9_host_config] | + community.general.lists_mergeby('name', recursive=true, list_merge='append_rp') + }} diff --git a/docs/BIND9_9.20_SUPPORT.md b/docs/BIND9_9.20_SUPPORT.md new file mode 100644 index 0000000..55875a6 --- /dev/null +++ b/docs/BIND9_9.20_SUPPORT.md @@ -0,0 +1,231 @@ +# BIND9 9.20 Support Implementation Guide + +## Overview + +This document describes the ansible-bind9-role implementation for BIND9 9.20+ support through the `feature/bind9-20-support` branch. + +## Architecture + +### Multi-Version Support Strategy + +The role supports multiple BIND9 versions using: + +1. **Runtime Version Detection**: BIND9 version is detected at runtime and stored in the `bind9_version` fact +2. **Template Conditionals**: Jinja2 conditionals in templates apply version-specific configurations +3. **Separate Branches**: Different BIND9 feature release series are maintained on separate branches + - `main`: BIND9 9.18.x (LTS) - Production stable + - `9.20`: BIND9 9.20+ (feature releases) - New features and modern approach + +### Branch Structure + +``` +main # BIND9 9.18.x LTS (stable) +│ +└─ 9.20 # BIND9 9.20+ feature releases + ├─ feature/bind9-20-support # Current development branch + └─ (will merge to 9.20 after testing) +``` + +## Implementation Details + +### 1. Version Detection (tasks/main.yml) + +```yaml +- name: Detect BIND9 version at runtime + ansible.builtin.command: + cmd: named -v + register: _bind9_version_output + changed_when: false + +- name: Set bind9_version fact + ansible.builtin.set_fact: + bind9_version: "{{ _bind9_version_output.stdout | regex_search('BIND (\\S+)', '\\1') | first }}" +``` + +### 2. Meta/Argument Specs Updates + +The `meta/argument_specs.yml` has been updated to: + +- Document BIND9 9.20+ support alongside 9.18.x +- Add `bind9_version` variable documentation (read-only, auto-detected) +- Clarify version-specific behavior + +### 3. Molecule Testing + +Two molecule scenarios are now available: + +#### Default Scenario (BIND9 9.18.x) +- **Location**: `molecule/default/` +- **Platform**: Debian 13 (Trixie) with BIND9 9.18.x +- **Purpose**: Validate production-stable configurations + +#### BIND9 9.20 Scenario +- **Location**: `molecule/bind9-20/` +- **Platform**: Ubuntu 24.04 LTS with BIND9 9.20+ +- **Purpose**: Validate newer configurations and breaking changes +- **Tests**: Forward zones, TLS, DNSTAP, modern DNSSEC + +### 4. Template Version Compatibility + +Templates have been audited for BIND9 9.20 compatibility. The primary template files include: + +- `named.conf.options.j2` - Global options block +- `named.conf.zone.j2` - Zone definitions +- `named.conf.primaries.j2` - Primary/secondary definitions +- `named.conf.tls.j2` - TLS configurations (9.20 focus) +- `named.conf.dnssec-policy.j2` - DNSSEC policies + +### 5. Deprecated Options Handling + +BIND9 9.20 removes 44 options from 9.18. The role handles this through: + +1. **Documentation**: Each deprecated option is documented in BIND9_MIGRATION_GUIDE.md +2. **Conditional Removal**: Templates check version and exclude removed options +3. **Migration Path**: BIND9_MIGRATION_GUIDE.md provides alternatives for each removed option + +## Critical BIND9 9.20 Changes + +### Automatically Enabled Options + +These cannot and should not be configured (always enabled in 9.20): + +- `glue-cache` - Glue records are always cached +- `keep-response-order` - Response ordering is always enabled +- `reuse` - TCP socket reuse is always enabled + +### Removed Global Options + +Key removed options requiring configuration changes: + +| 9.18 Option | 9.20 Replacement | +|---|---| +| `alt-transfer-source` | Use TLS in `primaries` statement | +| `alt-transfer-source-v6` | Use TLS in `primaries` statement | +| `auto-dnssec` | Automatic (DNSSEC always managed) | +| `dsc` | Use TLS configuration instead | +| `gssapi-credential` | Use TSIG + TLS instead | +| `heartbeat-interval` | Zone transfer monitoring improved | +| `lock-file` | OS-level locking used | +| `max-zone-ttl` | Use per-zone option instead | +| `parental-agents` | Use enhanced `primaries` statement | +| `parental-registration-delay` | Zone monitoring improved | +| `root-delegation-only` | Zone constraints | +| `suppress-initial-notify` | NOTIFY behavior changed | +| `tkeydhkey` | Use modern TLS/DNSSEC | +| `tkeygsapi-credential` | Use TSIG + TLS | + +### New 9.20 Features + +- **Native TLS/DoT Support**: Zone transfers over TLS +- **Automatic DNSSEC Management**: DNSSEC is handled automatically +- **Enhanced HTTP/HTTPS Server**: Built-in HTTP API +- **Better Resolver Behavior**: Improved retry and fallback logic +- **Query Monitoring**: Advanced query tracking and statistics + +## Configuration Changes for 9.20 + +### Before (BIND9 9.18.x) + +```yaml +bind9_default_config: + - name: named.conf.options + options: + alt_transfer_source: 10.0.1.1 + glue_cache: yes + parental_agents: + - 192.0.2.1 + - 192.0.2.2 +``` + +### After (BIND9 9.20+) + +```yaml +bind9_default_config: + - name: named.conf.options + options: + # Removed: alt_transfer_source, glue_cache, parental_agents + # Instead use TLS and enhanced primaries statement + - name: named.conf.zone + zones: + - name: example.com + type: secondary + primaries: + - address: 192.0.2.1 + tls: zone-transfer-tls # New 9.20 approach + - address: 192.0.2.2 + tls: zone-transfer-tls +``` + +## Testing the Implementation + +### Running Molecule Tests + +```bash +# Test both scenarios +molecule test + +# Test only 9.18 scenario +molecule test -s default + +# Test only 9.20 scenario +molecule test -s bind9-20 + +# Interactive testing +molecule create -s bind9-20 +molecule converge -s bind9-20 +molecule verify -s bind9-20 +``` + +### Manual Validation + +```bash +# Check BIND9 version +named -v + +# Validate configuration syntax +named-checkconf /etc/bind/named.conf + +# Check logs for version-related messages +journalctl -u named -n 50 -e +tail -f /var/log/named/default.log +``` + +## Migration Path + +Users upgrading from 9.18 to 9.20 should: + +1. **Review Configuration**: Check `BIND9_MIGRATION_GUIDE.md` for breaking changes +2. **Update Playbooks**: Remove deprecated variables/options +3. **Test in Staging**: Use `molecule test -s bind9-20` to validate +4. **Gradual Migration**: Test on non-critical servers first +5. **Monitor Logs**: Watch for deprecation or error messages + +## Future Enhancements + +- [ ] Automated configuration migration tool +- [ ] Deprecation warnings in role output +- [ ] 9.21+ preparation when available +- [ ] Performance tuning for 9.20 features +- [ ] DNS-over-HTTPS (DoH) support +- [ ] Clustering/high-availability examples + +## References + +- [ISC BIND9 Website](https://www.isc.org/bind/) +- [BIND9 9.20 Release Notes](https://www.isc.org/download/news/) +- [BIND9 Documentation](https://bind9.readthedocs.io/) +- [BIND9 Version Differences](../../docs/BIND_VERSION_DIFFERENCES.md) +- [BIND9 Migration Guide](../../docs/BIND9_MIGRATION_GUIDE.md) +- [VERSION_SUPPORT.md](../../docs/VERSION_SUPPORT.md) + +## Support + +For issues or questions about BIND9 9.20 support: + +1. Check existing [Issues](https://git.valid.dk/daniel/ansible-bind9-role/issues) +2. Review [Discussions](https://git.valid.dk/daniel/ansible-bind9-role/discussions) +3. Create a new issue with: + - BIND9 version (`named -v`) + - Playbook configuration + - Error messages from logs + - Steps to reproduce diff --git a/docs/BIND9_MIGRATION_GUIDE.md b/docs/BIND9_MIGRATION_GUIDE.md new file mode 100644 index 0000000..8129079 --- /dev/null +++ b/docs/BIND9_MIGRATION_GUIDE.md @@ -0,0 +1,479 @@ +# BIND9 9.18 to 9.20 Migration Guide + +## Overview + +This guide provides step-by-step instructions for migrating BIND9 configurations from version 9.18.x (LTS) to version 9.20.x. + +**Important:** BIND9 9.20 introduces 44 breaking changes. Before upgrading, carefully review this guide and test in a development environment. + +For detailed technical differences between versions, see [BIND9 Version Differences](BIND_VERSION_DIFFERENCES.md). + +## Table of Contents + +1. [Pre-Migration Planning](#pre-migration-planning) +2. [Breaking Changes Summary](#breaking-changes-summary) +3. [Migration Steps](#migration-steps) +4. [Configuration Examples](#configuration-examples) +5. [Role-Specific Changes](#role-specific-changes) +6. [Testing Recommendations](#testing-recommendations) +7. [Rollback Procedure](#rollback-procedure) + +## Pre-Migration Planning + +### Check Your Configuration + +Before upgrading, identify which BIND9 options your configuration uses: + +```bash +# Check for options that will be removed +named-checkconf -p /etc/bind/named.conf | \ + grep -E "alt-transfer-source|auto-dnssec|coresize|datasize|glue-cache" +``` + +### Create Backups + +```bash +# Backup all BIND configuration +cp -r /etc/bind /data/backup/bind.9.18.backup + +# Backup BIND data +cp -r /var/lib/bind /data/backup/bind.9.18.data +cp -r /var/cache/bind /data/backup/bind.9.18.cache +``` + +### Review Version Support + +This Ansible role is designed for BIND9 9.18.x. When upgrading to 9.20: + +- The main branch will continue supporting 9.18.x +- A separate `9.20` branch will provide 9.20-specific templates and configurations +- Use the appropriate branch for your target BIND9 version + +## Breaking Changes Summary + +The following options are **removed** in BIND9 9.20 and will cause `named` to fail if present: + +### Global Options (9.20 Breaking Changes) + +- `alt-transfer-source` - Use TLS-based transfers instead +- `alt-transfer-source-v6` - Use TLS-based transfers instead +- `auto-dnssec` - DNSSEC management is automatic in 9.20 +- `coresize` - System resource limits; use OS-level controls +- `datasize` - System resource limits; use OS-level controls +- `dscp` - Use TLS configuration instead +- `files` - System resource limits; use OS-level controls +- `glue-cache` - Always enabled in 9.20 +- `heartbeat-interval` - Zone transfer changes +- `keep-response-order` - Always enabled in 9.20 +- `lock-file` - Use system lock controls +- `maxz-zone-ttl` - Use `max-zone-ttl` instead (per-zone option) +- `parent-registration-delay` - Zone-delegation monitoring removed +- `parental-agents` - Use `primaries` statement with DNSSEC +- `primaries` - Replaced with enhanced syntax (see below) +- `random-device` - System entropy handling improved +- `recurse-ing-file` - Renamed to `recursing-file` +- `reserved-sockets` - Automatic in 9.20 +- `resolver-nonbackoff-tries` - Resolver behavior changed +- `resolver-retry-interval` - Resolver behavior changed +- `reuse` - Always enabled in 9.20 +- `root-delegation-only` - Removed; not needed in 9.20 +- `stacksize` - System resource limits; use OS-level controls +- `suppress-initial-notify` - NOTIFY behavior changed +- `tkey-dhkey` - Use modern TLS/DNSSEC instead +- `tkey-gssapi-credential` - Use TSIG + TLS instead + +### Zone-Type Specific Breaking Changes + +#### All Zone Types +- `delegation-only` - Removed; use zone type constraints instead +- `alt-transfer-source[v6]` - Use TLS configuration +- `auto-dnssec` - DNSSEC management changes +- `use-alt-transfer-source` - Use TLS configuration + +## Migration Steps + +### Step 1: Identify Configuration Changes + +Review your current `bind9_*_config` variables for any deprecated options: + +```yaml +# Search your inventory and host_vars for these patterns +bind9_default_config: + - name: named.conf.options + options: + # These options must be removed or replaced: + # - alt_transfer_source + # - auto_dnssec + # - glue_cache + # ... etc +``` + +### Step 2: Update Ansible Variables + +Replace deprecated options in your Ansible configuration: + +```yaml +# BEFORE (BIND9 9.18) +bind9_default_config: + - name: named.conf.options + options: + alt_transfer_source: 10.0.1.1 + glue_cache: yes + keep_response_order: yes + +# AFTER (BIND9 9.20) +bind9_default_config: + - name: named.conf.options + options: + # alt_transfer_source removed - use TLS + # glue_cache removed - always enabled + # keep_response_order removed - always enabled + # Instead configure TLS for transfers + http: + preference: https +``` + +### Step 3: Update Primaries Configuration + +The `primaries` statement syntax has changed: + +```yaml +# BEFORE (BIND9 9.18) +bind9_host_config: + - name: named.conf.view + view: + - name: internal + zone: + - name: example.com + type: secondary + primaries: + - 192.0.2.1 + - 192.0.2.2 + +# AFTER (BIND9 9.20) +bind9_host_config: + - name: named.conf.view + view: + - name: internal + zone: + - name: example.com + type: secondary + primaries: + - address: 192.0.2.1 + - address: 192.0.2.2 + # Optional: TLS configuration + # tls: cert-name + # source: 10.0.1.1 + # source_v6: "2001:db8::1" +``` + +### Step 4: Validate Configuration + +Before deploying to production: + +```bash +# Validate syntax +named-checkconf /etc/bind/named.conf + +# Check for deprecated options +grep -r "alt-transfer-source\|auto-dnssec\|glue-cache" /etc/bind/ +``` + +### Step 5: Test Zone Operations + +```bash +# Test zone transfers +dig @ns1.example.com example.com AXFR + +# Test DNSSEC validation +dig @ns1.example.com example.com +dnssec + +# Check BIND logs +journalctl -u bind9 -f +``` + +## Configuration Examples + +### Example 1: Simple Secondary Zone Migration + +**BIND9 9.18 Configuration:** + +```yaml +bind9_default_config: + - name: named.conf.view + view: + - name: "default" + recursion: yes + zone: + - name: "example.com" + type: "secondary" + file: "/var/lib/bind/example.com.zone" + primaries: + - 192.0.2.1 + - 192.0.2.2 + alt_transfer_source: 10.0.1.1 + alt_transfer_source_v6: "2001:db8::1" + allow_transfer: + - 10.0.2.0/24 +``` + +**BIND9 9.20 Configuration:** + +```yaml +bind9_default_config: + - name: named.conf.view + view: + - name: "default" + recursion: yes + zone: + - name: "example.com" + type: "secondary" + file: "/var/lib/bind/example.com.zone" + primaries: + - address: 192.0.2.1 + - address: 192.0.2.2 + # alt_transfer_source removed - use TLS + # Configuration now uses single source per address: + allow_transfer: + - 10.0.2.0/24 +``` + +### Example 2: DNSSEC Configuration Migration + +**BIND9 9.18 Configuration:** + +```yaml +bind9_default_config: + - name: named.conf.options + options: + dnssec_policy: default + - name: named.conf.zone + zone: + - name: "example.com" + type: "primary" + file: "/var/lib/bind/example.com.zone" + auto_dnssec: maintain + inline_signing: yes +``` + +**BIND9 9.20 Configuration:** + +```yaml +bind9_default_config: + - name: named.conf.options + options: + dnssec_policy: default + - name: named.conf.zone + zone: + - name: "example.com" + type: "primary" + file: "/var/lib/bind/example.com.zone" + # auto_dnssec removed - DNSSEC management is automatic + dnssec_policy: default # Explicitly set policy + inline_signing: yes # Still supported +``` + +## Role-Specific Changes + +### Branch Selection + +When using this Ansible role with BIND9 9.20, you have two options: + +#### Option 1: Use Main Branch (Recommended for 9.18) + +```bash +# Use main branch for BIND9 9.18 +ansible-galaxy install daniel.ansible-bind9-role +``` + +#### Option 2: Use 9.20 Branch (When Available) + +```bash +# Clone the 9.20 branch for BIND9 9.20 support +git clone --branch 9.20 https://git.valid.dk/daniel/ansible-bind9-role.git +``` + +### Template Variables + +No Ansible variable names change between versions. However, the **values** for some variables may need adjustment: + +```yaml +# Variable names stay the same (kebab-case → snake_case) +# Example: "alt-transfer-source" → "alt_transfer_source" +# Simply remove deprecated variables - they will be ignored + +bind9_default_config: + - name: named.conf.options + options: + # Remove these: + # alt_transfer_source: ... + # auto_dnssec: ... + # glue_cache: ... + + # These still work: + dnssec_validation: yes + recursion: yes + allow_query: + - any +``` + +### DNSSEC Policy Changes + +BIND9 9.20 improves DNSSEC handling: + +```yaml +# Both versions support dnssec_policy +bind9_default_config: + - name: named.conf.dnssec-policy + dnssec_policy: + - name: default + keys: + - lifetime: 3600 + algorithm: ecdsap256sha256 + role: + - ksk + - zsk + nsec3param: + iterations: 0 + optout: no + salt_length: 32 +``` + +## Testing Recommendations + +### Test Environment Setup + +Create a test playbook to validate migration: + +```yaml +--- +- hosts: test_servers + vars: + bind9_version: "9.20" # Document version being tested + + tasks: + - name: Apply BIND9 9.20 configuration + include_role: + name: ansible-bind9-role + + - name: Validate configuration + command: named-checkconf /etc/bind/named.conf + register: config_check + failed_when: config_check.rc != 0 + + - name: Test zone transfers + command: > + dig @localhost example.com AXFR + register: zone_transfer + + - name: Test DNSSEC validation + command: > + dig @localhost example.com +dnssec + register: dnssec_test + + - name: Check BIND status + systemd: + name: bind9 + state: started + register: bind_status +``` + +### Validation Checklist + +- [ ] Configuration syntax valid (`named-checkconf`) +- [ ] BIND9 service starts without errors +- [ ] All zones load successfully +- [ ] Zone transfers complete successfully +- [ ] Queries resolve correctly +- [ ] DNSSEC validation works +- [ ] Secondary zones receive updates +- [ ] No errors in BIND logs +- [ ] Performance is acceptable + +## Rollback Procedure + +If issues occur after migration: + +### Immediate Rollback + +```bash +# Stop BIND9 +systemctl stop bind9 + +# Restore configuration backup +rm -rf /etc/bind +cp -r /data/backup/bind.9.18.backup /etc/bind + +# Restore zone files +rm -rf /var/lib/bind +cp -r /data/backup/bind.9.18.data /var/lib/bind +cp -r /data/backup/bind.9.18.cache /var/cache/bind + +# Restore BIND9 package +apt-get install --reinstall bind9=1:9.18.44-1+0~20240101.3+debian~bullseye+1+sury+1 + +# Start BIND9 +systemctl start bind9 + +# Verify +systemctl status bind9 +dig @localhost example.com +``` + +### Using Ansible Rollback + +```yaml +--- +- hosts: bind_servers + tasks: + - name: Restore BIND9 9.18 package + apt: + name: bind9=1:9.18.44-1+0~20240101.3+debian~bullseye+1+sury+1 + state: present + + - name: Restore configuration from backup + synchronize: + src: /data/backup/bind.9.18.backup/ + dest: /etc/bind/ + delete: yes + mode: push + + - name: Restart BIND9 + systemd: + name: bind9 + state: restarted + daemon_reload: yes +``` + +## Additional Resources + +- [BIND9 Version Differences](BIND_VERSION_DIFFERENCES.md) - Technical comparison +- [ISC BIND9 Release Notes](https://www.isc.org/bind/) - Official documentation +- [BIND9 9.20 Features](https://bind.readthedocs.io/en/latest/) - Feature details +- [Role Configuration Reference](CONFIGURATION_GRAMMAR.md) - Ansible role documentation + +## Getting Help + +For issues during migration: + +1. Check [BIND9 Version Differences](BIND_VERSION_DIFFERENCES.md) for specific option changes +2. Review BIND9 logs: `journalctl -u bind9 -n 100` +3. Validate configuration: `named-checkconf /etc/bind/named.conf` +4. Test in development environment first +5. Document any custom options that need special handling + +## Version Support Timeline + +- **BIND9 9.18.x (LTS)**: Supported until September 2026 + - This Ansible role's current focus + - Main branch targets 9.18.x configurations + +- **BIND9 9.20.x**: Available now + - Future branch (`9.20`) being prepared + - Plan migration during non-critical periods + +- **BIND9 9.22.x**: Coming in 2026 + - Further breaking changes expected + - Will require additional migration steps + +Plan upgrades within your maintenance windows and test thoroughly before production deployment. diff --git a/docs/BIND_VERSION_DIFFERENCES.md b/docs/BIND_VERSION_DIFFERENCES.md new file mode 100644 index 0000000..3076c2f --- /dev/null +++ b/docs/BIND_VERSION_DIFFERENCES.md @@ -0,0 +1,552 @@ +# BIND9 Version Differences: v9.18.44 vs v9.20.18 + +This document compares BIND9 configuration grammar between v9.18.44 and v9.20.18. + +Generated automatically by `scripts/compare_bind_versions.py`. + +## Summary + +- **New Options**: 35 +- **Removed Options**: 44 ⚠️ +- **Modified Options**: 22 +- **Newly Deprecated**: 3 + +## ⚠️ Breaking Changes + +The following options were removed in v9.20.18 and will cause configuration errors: + +### options + +- `alt-transfer-source` +- `alt-transfer-source-v6` +- `auto-dnssec` +- `coresize` +- `datasize` +- `dscp` +- `files` +- `glue-cache` +- `heartbeat-interval` +- `keep-response-order` +- `lock-file` +- `maxz-zone-ttl` +- `parent-registration-delay` +- `parental-agents` +- `primaries` +- `random-device` +- `recurse-ing-file` +- `reserved-sockets` +- `resolver-nonbackoff-tries` +- `resolver-retry-interval` +- `reuse` +- `root-delegation-only` +- `stacksize` +- `suppress-initial-notify` +- `tkey-dhkey` +- `tkey-gssapi-credential` +- `use-alt-transfer-source` + +### forward.zoneopt + +- `delegation-only` + +### hint.zoneopt + +- `delegation-only` + +### mirror.zoneopt + +- `alt-transfer-source` +- `alt-transfer-source-v6` +- `use-alt-transfer-source` + +### primary.zoneopt + +- `alt-transfer-source` +- `alt-transfer-source-v6` +- `auto-dnssec` +- `update-check-ksk` + +### secondary.zoneopt + +- `alt-transfer-source` +- `alt-transfer-source-v6` +- `auto-dnssec` +- `use-alt-transfer-source` + +### stub.zoneopt + +- `delegation-only` +- `use-alt-transfer-source` + +### delegation-only.zoneopt + +- `type` +- `zone` + +## ✨ New Features + +The following options were added in v9.20.18: + +### options + +- `allow-proxy` +- `allow-proxy-on` +- `cdnskey` +- `cds-digest-types` +- `check-svcb` +- `cipher-suites` +- `dnsrps-library` +- `inline-signing` +- `key-store` +- `manual-mode` +- `max-validation-failures-per-fetch` +- `max-validations-per-fetch` +- `min-transfer-rate-in` +- `notify-defer` +- `offline-ksk` +- `pkcs11-uri` +- `recursing-file` +- `remote-servers` +- `require-cookie` +- `resolver-use-dns64` +- `responselog` +- `reuseport` +- `sig0-checks-quota` +- `sig0-checks-quota-exempt` +- `sig0-key-checks-limit` +- `sig0-message-checks-limit` + +### mirror.zoneopt + +- `min-transfer-rate-in` +- `notify-defer` + +### primary.zoneopt + +- `check-svcb` +- `checkds` +- `notify-defer` + +### secondary.zoneopt + +- `checkds` +- `min-transfer-rate-in` +- `notify-defer` + +### stub.zoneopt + +- `min-transfer-rate-in` + +## 🔧 Modified Options + +The following options have syntax changes in v9.20.18: + +### options + +#### `listen-on` + +**v9.18.44**: +``` +[ port ] [ tls ] [ http ] { +``` + +**v9.20.18**: +``` +[ port ] [ proxy ] [ tls ] [ http ] { +``` + +#### `response-policy` + +**v9.18.44**: +``` +{ zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] +``` + +**v9.20.18**: +``` +{ zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ] +``` + +#### `cookie-algorithm` + +**v9.18.44**: +``` +( aes | siphash24 ) +``` + +**v9.20.18**: +``` +( siphash24 ) +``` + +#### `forwarders` + +**v9.18.44**: +``` +[ port ] { ( | ) [ port ] +``` + +**v9.20.18**: +``` +[ port ] [ tls ] { ( | ) [ port ] [ tls ] +``` + +#### `listen-on-v6` + +**v9.18.44**: +``` +[ port ] [ tls ] [ http ] { +``` + +**v9.20.18**: +``` +[ port ] [ proxy ] [ tls ] [ http ] { +``` + +#### `also-notify` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +#### `catalog-zones` + +**v9.18.44**: +``` +{ zone [ default-primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +{ zone [ default-primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +### forward.zoneopt + +#### `forwarders` + +**v9.18.44**: +``` +[ port ] { ( | ) [ port ] +``` + +**v9.20.18**: +``` +[ port ] [ tls ] { ( | ) [ port ] [ tls ] +``` + +### mirror.zoneopt + +#### `also-notify` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +#### `primaries` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +### primary.zoneopt + +#### `update-policy` + +**v9.18.44**: +``` +( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesubject ) [ ] +``` + +**v9.20.18**: +``` +( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ ] +``` + +#### `also-notify` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +#### `parental-agents` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +#### `forwarders` + +**v9.18.44**: +``` +[ port ] { ( | ) [ port ] +``` + +**v9.20.18**: +``` +[ port ] [ tls ] { ( | ) [ port ] [ tls ] +``` + +### redirect.zoneopt + +#### `primaries` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +### secondary.zoneopt + +#### `also-notify` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +#### `parental-agents` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +#### `forwarders` + +**v9.18.44**: +``` +[ port ] { ( | ) [ port ] +``` + +**v9.20.18**: +``` +[ port ] [ tls ] { ( | ) [ port ] [ tls ] +``` + +#### `primaries` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +### static-stub.zoneopt + +#### `forwarders` + +**v9.18.44**: +``` +[ port ] { ( | ) [ port ] +``` + +**v9.20.18**: +``` +[ port ] [ tls ] { ( | ) [ port ] [ tls ] +``` + +### stub.zoneopt + +#### `forwarders` + +**v9.18.44**: +``` +[ port ] { ( | ) [ port ] +``` + +**v9.20.18**: +``` +[ port ] [ tls ] { ( | ) [ port ] [ tls ] +``` + +#### `primaries` + +**v9.18.44**: +``` +[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +**v9.20.18**: +``` +[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ] +``` + +## 📋 Newly Deprecated Options + +The following options were marked as deprecated in v9.20.18: + +### options + +- `sortlist` + +### primary.zoneopt + +- `max-zone-ttl` + +### redirect.zoneopt + +- `max-zone-ttl` + +## Detailed File-by-File Comparison + +### options + +- v9.18.44: 334 options +- v9.20.18: 333 options +- Added: 26 +- Removed: 27 +- Modified: 7 + +### forward.zoneopt + +- v9.18.44: 5 options +- v9.20.18: 4 options +- Added: 0 +- Removed: 1 +- Modified: 1 + +### hint.zoneopt + +- v9.18.44: 5 options +- v9.20.18: 4 options +- Added: 0 +- Removed: 1 +- Modified: 0 + +### in-view.zoneopt + +- v9.18.44: 2 options +- v9.20.18: 2 options +- Added: 0 +- Removed: 0 +- Modified: 0 + +### mirror.zoneopt + +- v9.18.44: 44 options +- v9.20.18: 43 options +- Added: 2 +- Removed: 3 +- Modified: 2 + +### primary.zoneopt + +- v9.18.44: 63 options +- v9.20.18: 62 options +- Added: 3 +- Removed: 4 +- Modified: 4 + +### redirect.zoneopt + +- v9.18.44: 14 options +- v9.20.18: 14 options +- Added: 0 +- Removed: 0 +- Modified: 1 + +### secondary.zoneopt + +- v9.18.44: 66 options +- v9.20.18: 65 options +- Added: 3 +- Removed: 4 +- Modified: 4 + +### static-stub.zoneopt + +- v9.18.44: 12 options +- v9.20.18: 12 options +- Added: 0 +- Removed: 0 +- Modified: 1 + +### stub.zoneopt + +- v9.18.44: 28 options +- v9.20.18: 27 options +- Added: 1 +- Removed: 2 +- Modified: 2 + +### delegation-only.zoneopt + +- v9.18.44: 2 options +- v9.20.18: 0 options +- Added: 0 +- Removed: 2 +- Modified: 0 + +### rndc.grammar + +- v9.18.44: 14 options +- v9.20.18: 14 options +- Added: 0 +- Removed: 0 +- Modified: 0 + +## Migration Guide + +### Migrating from v9.18.44 to v9.20.18 + +1. **Remove unsupported options** from your configuration + - Review the Breaking Changes section above + - Check if there are replacement options + +2. **Plan for deprecated options** + - These options still work but may be removed in future versions + - Start planning migration to recommended alternatives + +3. **Test your configuration** + - Use `named-checkconf` to validate syntax + - Test in a development environment before production diff --git a/docs/VERSION_SUPPORT.md b/docs/VERSION_SUPPORT.md new file mode 100644 index 0000000..6009f61 --- /dev/null +++ b/docs/VERSION_SUPPORT.md @@ -0,0 +1,370 @@ +# BIND9 Version Support Policy + +**Document Version**: 1.0 +**Last Updated**: 2026-02-07 +**Role Version**: Current development + +## Overview + +This document defines the version maintenance strategy for the ansible-bind9-role, including supported BIND9 versions, OS platforms, branching strategy, and release management policies. + +## Supported Versions + +### BIND9 Versions + +| BIND9 Version | Branch | Status | Support Level | EOL Date | +|---------------|--------|--------|---------------|----------| +| 9.18.x (LTS) | `main` | ✅ Active | Full support | TBD (following ISC LTS timeline) | +| 9.20.x+ | `9.20` | 🚧 In Development | Planned | N/A | + +#### Version Selection Rationale + +- **BIND9 9.18**: Long Term Support (LTS) release from ISC + - Maintained by ISC with extended support timeline + - Stable feature set suitable for production environments + - Current focus of this role + +- **BIND9 9.20+**: Feature release series + - Introduces significant configuration changes + - New features and modernization + - May have shorter support windows per release + - Will be supported in separate branch to prevent breaking changes + +### Operating System Support Matrix + +| OS Distribution | Versions | BIND9 9.18 | BIND9 9.20+ | Notes | +|----------------|----------|------------|-------------|-------| +| Debian | 11 (Bullseye) | ✅ Supported | 🔍 Testing | Current stable | +| Debian | 12 (Bookworm) | ✅ Supported | ✅ Supported | Current testing focus | +| Debian | 13 (Trixie) | ✅ Supported | ✅ Supported | Future stable | +| Ubuntu | 20.04 LTS | ✅ Supported | 🔍 Testing | LTS until 2025 | +| Ubuntu | 22.04 LTS | ✅ Supported | ✅ Supported | LTS until 2027 | +| Ubuntu | 24.04 LTS | ✅ Supported | ✅ Supported | LTS until 2029 | + +**Legend**: +- ✅ Supported: Fully tested and supported +- 🔍 Testing: In testing, use with caution +- ⚠️ Limited: Basic support only +- ❌ Unsupported: Not supported + +### Minimum Requirements + +- **Ansible**: 2.13 or later +- **Python**: 3.8 or later (on controller and managed nodes) +- **BIND9 Packages**: Must be available in distribution repositories or custom sources + +## Branching Strategy + +### Branch Structure + +``` +main # BIND9 9.18 LTS (stable) +├── 9.20 # BIND9 9.20+ development +├── docs # Documentation updates (merged to both) +└── feature/* # Feature branches (target appropriate base) +``` + +### Branch Policies + +#### `main` Branch +- **Purpose**: Production-ready code for BIND9 9.18 LTS +- **Stability**: Stable, tested releases only +- **Breaking Changes**: Not allowed +- **Version Tagging**: `v1.x.x`, `v2.x.x`, etc. + +#### `9.20` Branch +- **Purpose**: Development for BIND9 9.20+ support +- **Stability**: Development/testing phase +- **Breaking Changes**: Allowed (vs 9.18 configurations) +- **Version Tagging**: `v9.20.x-betaX`, `v9.20.x-rcX`, `v9.20.x` + +#### Feature Branches +- **Naming**: `feature/description` or `fix/issue-number` +- **Target**: Merge to appropriate base (`main` for 9.18, `9.20` for 9.20+) +- **Lifecycle**: Delete after merge + +### Backporting Policy + +#### Security Fixes +- **Policy**: MUST be backported to all supported branches +- **Timeline**: Within 48 hours of fix +- **Priority**: Critical + +#### Bug Fixes +- **Policy**: SHOULD be backported if: + - Affects both versions + - Low risk of introducing regressions + - Reasonable effort required +- **Timeline**: Within 1 week +- **Priority**: High + +#### New Features +- **Policy**: Case-by-case evaluation +- **Criteria**: + - Feature is compatible with both BIND9 versions + - Does not introduce breaking changes + - Provides significant value + - Low implementation complexity +- **Timeline**: Best effort +- **Priority**: Medium + +#### Breaking Changes +- **Policy**: NEVER backported +- **Implementation**: Only in version-specific branches + +## Release Management + +### Version Numbering + +Following [Semantic Versioning 2.0.0](https://semver.org/): + +``` +MAJOR.MINOR.PATCH + +MAJOR: Incompatible API changes (role variable structure changes) +MINOR: New functionality in a backwards compatible manner +PATCH: Backwards compatible bug fixes +``` + +#### Examples + +- `v1.2.3`: Patch release for BIND9 9.18 +- `v2.0.0`: Major release with breaking role variable changes +- `v9.20.0-beta1`: Beta release for BIND9 9.20 support +- `v9.20.0`: First stable release for BIND9 9.20 + +### Release Cadence + +- **Patch Releases**: As needed for bug fixes and security updates +- **Minor Releases**: Quarterly (or when significant features accumulate) +- **Major Releases**: Annually (or when breaking changes are necessary) + +### Pre-release Testing + +All releases must pass: +1. **Molecule tests** across all supported platforms +2. **named-checkconf** validation for all example configurations +3. **Manual testing** on at least 2 different distributions +4. **Documentation review** and update + +### Release Checklist + +- [ ] Update `CHANGELOG.md` with all changes +- [ ] Update version in `meta/main.yml` +- [ ] Run full molecule test suite +- [ ] Update `README.md` if needed +- [ ] Create annotated git tag +- [ ] Push tag to trigger CI/CD +- [ ] Create GitHub/Gitea release with notes +- [ ] Announce on project channels + +## Testing Strategy + +### Test Matrix + +#### Molecule Scenarios + +| Scenario | Distribution | BIND9 Version | Purpose | +|----------|--------------|---------------|---------| +| default | Debian 13 | 9.18 | Primary development testing | +| ubuntu2204 | Ubuntu 22.04 | 9.18 | LTS testing | +| ubuntu2404 | Ubuntu 24.04 | 9.18/9.20 | Future-proofing | +| debian12 | Debian 12 | 9.18 | Stable release testing | + +#### Test Coverage + +- **Syntax validation**: All templates pass `named-checkconf` +- **Service management**: Start, stop, reload, restart operations +- **Configuration types**: All zone types and statement blocks +- **Edge cases**: Empty configurations, complex nested structures +- **Upgrade scenarios**: Migration from previous role versions + +### Continuous Integration + +```yaml +# .github/workflows/test.yml (example structure) +on: [push, pull_request] +jobs: + molecule: + strategy: + matrix: + distro: [debian12, debian13, ubuntu2204, ubuntu2404] + bind_version: ['9.18', '9.20'] + exclude: + # Don't test 9.20 on older distributions + - distro: ubuntu2004 + bind_version: '9.20' +``` + +## Grammar Tracking and Validation + +### Automated Grammar Comparison + +The role maintains upstream BIND9 grammar files to: +1. Detect configuration syntax changes between versions +2. Identify deprecated and removed options +3. Document breaking changes for users + +#### Grammar Repository Structure + +``` +bind9-grammar/ +├── upstream/ +│ ├── v9.18.44/ # Latest 9.18 LTS grammar +│ │ ├── grammar/ +│ │ │ ├── options +│ │ │ ├── *.zoneopt +│ │ │ └── parsegrammar.py +│ │ └── metadata.json +│ └── v9.20.18/ # Latest 9.20 grammar +│ ├── grammar/ +│ └── metadata.json +├── 9.18/ # Current 9.18 JSON schemas +│ └── *.json +└── 9.20/ # Future 9.20 JSON schemas + └── *.json +``` + +### Validation Tools + +#### `scripts/fetch_bind_grammar.py` +- Fetches grammar files from Gitea mirror (`Mirrors/bind9`) +- Supports version tags (e.g., `v9.18.44`, `v9.20.18`) +- Stores upstream grammar for comparison + +#### `scripts/compare_bind_versions.py` +- Compares grammar files between versions +- Generates `docs/BIND_VERSION_DIFFERENCES.md` +- Identifies: + - Breaking changes (removed options) + - New features (added options) + - Modified syntax + - Deprecation notices + +### Grammar Update Workflow + +1. **Monitor**: Watch Gitea mirror for new BIND9 releases +2. **Fetch**: Run `fetch_bind_grammar.py` for new version +3. **Compare**: Run `compare_bind_versions.py` to identify changes +4. **Review**: Analyze breaking changes and impact +5. **Update**: Modify templates and variables as needed +6. **Test**: Run molecule tests with new version +7. **Document**: Update `BIND_VERSION_DIFFERENCES.md` and `CHANGELOG.md` + +## Deprecation Policy + +### Deprecation Process + +1. **Announcement**: Document deprecation in `CHANGELOG.md` and `README.md` +2. **Warning Period**: Minimum 2 minor releases before removal +3. **Alternative**: Provide migration path or alternative approach +4. **Removal**: Only in major version releases + +### Current Deprecations + +*None at this time* + +### Planned Deprecations + +*To be determined based on BIND9 9.20 analysis* + +## Version-Specific Features + +### Version Detection + +The role will detect BIND9 version at runtime: + +```yaml +# tasks/main.yml (planned implementation) +- name: Detect BIND9 version + ansible.builtin.command: named -V + register: _bind9_version_output + changed_when: false + +- name: Set BIND9 version facts + ansible.builtin.set_fact: + bind9_version_full: "{{ _bind9_version_output.stdout | regex_search('BIND (\\S+)', '\\1') | first }}" + bind9_version_major: "{{ _bind9_version_output.stdout | regex_search('BIND (\\d+)\\.(\\d+)', '\\1') | first }}" + bind9_version_minor: "{{ _bind9_version_output.stdout | regex_search('BIND (\\d+)\\.(\\d+)', '\\2') | first }}" +``` + +### Conditional Configuration + +Templates will use version-aware conditionals: + +```jinja2 +{# templates/named.conf.options.j2 (planned) #} +{% if bind9_version_major | int >= 20 %} + {# BIND9 9.20+ specific options #} +{% else %} + {# BIND9 9.18 options #} +{% endif %} +``` + +## Migration Guidance + +### Migrating from BIND9 9.18 to 9.20 + +When BIND9 9.20 support is released: + +1. **Review**: Read `docs/BIND_VERSION_DIFFERENCES.md` +2. **Test**: Use `9.20` branch in test environment +3. **Update**: Modify playbook variables for deprecated/removed options +4. **Validate**: Run `named-checkconf` against generated configuration +5. **Deploy**: Upgrade BIND9 package and deploy new configuration +6. **Monitor**: Check logs for warnings or errors + +### Migrating Between Role Versions + +See `CHANGELOG.md` for version-specific migration notes. + +## Support and Contribution + +### Getting Help + +- **Issues**: Report bugs and request features on Gitea +- **Documentation**: Refer to `README.md` and `CONFIGURATION_GRAMMAR.md` +- **Examples**: Check `tests/` directory for working configurations + +### Contributing + +- **Bug Fixes**: Target `main` branch (or `9.20` if version-specific) +- **Features**: Discuss in issue before implementation +- **Testing**: Ensure molecule tests pass +- **Documentation**: Update relevant documentation files + +### Governance + +- **Maintainer**: Primary maintainer approves all merges +- **Review**: All changes require review before merge +- **Testing**: CI/CD must pass before merge + +## Future Considerations + +### BIND9 9.21+ and Beyond + +- Monitor ISC release announcements +- Evaluate need for additional branches +- Consider dropping support for EOL'd distributions +- Reassess branching strategy if maintenance burden increases + +### Automation Improvements + +- Automated grammar fetching in CI +- Automated breaking change detection +- Version compatibility testing matrix +- Documentation generation from grammar files + +## References + +- [ISC BIND9 Documentation](https://bind9.readthedocs.io/) +- [ISC BIND9 Release Schedule](https://www.isc.org/bind/) +- [Semantic Versioning](https://semver.org/) +- [Ansible Best Practices](https://docs.ansible.com/ansible/latest/tips_tricks/ansible_tips_tricks.html) + +## Changelog + +| Date | Version | Changes | +|------|---------|---------| +| 2026-02-07 | 1.0 | Initial version support policy | + diff --git a/docs/bind_version_comparison.json b/docs/bind_version_comparison.json new file mode 100644 index 0000000..06a783f --- /dev/null +++ b/docs/bind_version_comparison.json @@ -0,0 +1,326 @@ +{ + "options": { + "file": "options", + "added": [ + "allow-proxy", + "allow-proxy-on", + "cdnskey", + "cds-digest-types", + "check-svcb", + "cipher-suites", + "dnsrps-library", + "inline-signing", + "key-store", + "manual-mode", + "max-validation-failures-per-fetch", + "max-validations-per-fetch", + "min-transfer-rate-in", + "notify-defer", + "offline-ksk", + "pkcs11-uri", + "recursing-file", + "remote-servers", + "require-cookie", + "resolver-use-dns64", + "responselog", + "reuseport", + "sig0-checks-quota", + "sig0-checks-quota-exempt", + "sig0-key-checks-limit", + "sig0-message-checks-limit" + ], + "removed": [ + "alt-transfer-source", + "alt-transfer-source-v6", + "auto-dnssec", + "coresize", + "datasize", + "dscp", + "files", + "glue-cache", + "heartbeat-interval", + "keep-response-order", + "lock-file", + "maxz-zone-ttl", + "parent-registration-delay", + "parental-agents", + "primaries", + "random-device", + "recurse-ing-file", + "reserved-sockets", + "resolver-nonbackoff-tries", + "resolver-retry-interval", + "reuse", + "root-delegation-only", + "stacksize", + "suppress-initial-notify", + "tkey-dhkey", + "tkey-gssapi-credential", + "use-alt-transfer-source" + ], + "modified": [ + { + "option": "listen-on", + "old_definition": "[ port ] [ tls ] [ http ] { ", + "new_definition": "[ port ] [ proxy ] [ tls ] [ http ] { " + }, + { + "option": "response-policy", + "old_definition": "{ zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ]", + "new_definition": "{ zone [ add-soa ] [ log ] [ max-policy-ttl ] [ min-update-interval ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only ) ] [ recursive-only ] [ nsip-enable ] [ nsdname-enable ] [ ede ]" + }, + { + "option": "cookie-algorithm", + "old_definition": "( aes | siphash24 )", + "new_definition": "( siphash24 )" + }, + { + "option": "forwarders", + "old_definition": "[ port ] { ( | ) [ port ]", + "new_definition": "[ port ] [ tls ] { ( | ) [ port ] [ tls ]" + }, + { + "option": "listen-on-v6", + "old_definition": "[ port ] [ tls ] [ http ] { ", + "new_definition": "[ port ] [ proxy ] [ tls ] [ http ] { " + }, + { + "option": "also-notify", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + }, + { + "option": "catalog-zones", + "old_definition": "{ zone [ default-primaries [ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "{ zone [ default-primaries [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + } + ], + "deprecated_new": [ + "sortlist" + ], + "options1_count": 334, + "options2_count": 333 + }, + "forward.zoneopt": { + "file": "forward.zoneopt", + "added": [], + "removed": [ + "delegation-only" + ], + "modified": [ + { + "option": "forwarders", + "old_definition": "[ port ] { ( | ) [ port ]", + "new_definition": "[ port ] [ tls ] { ( | ) [ port ] [ tls ]" + } + ], + "deprecated_new": [], + "options1_count": 5, + "options2_count": 4 + }, + "hint.zoneopt": { + "file": "hint.zoneopt", + "added": [], + "removed": [ + "delegation-only" + ], + "modified": [], + "deprecated_new": [], + "options1_count": 5, + "options2_count": 4 + }, + "in-view.zoneopt": { + "file": "in-view.zoneopt", + "added": [], + "removed": [], + "modified": [], + "deprecated_new": [], + "options1_count": 2, + "options2_count": 2 + }, + "mirror.zoneopt": { + "file": "mirror.zoneopt", + "added": [ + "min-transfer-rate-in", + "notify-defer" + ], + "removed": [ + "alt-transfer-source", + "alt-transfer-source-v6", + "use-alt-transfer-source" + ], + "modified": [ + { + "option": "also-notify", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + }, + { + "option": "primaries", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + } + ], + "deprecated_new": [], + "options1_count": 44, + "options2_count": 43 + }, + "primary.zoneopt": { + "file": "primary.zoneopt", + "added": [ + "check-svcb", + "checkds", + "notify-defer" + ], + "removed": [ + "alt-transfer-source", + "alt-transfer-source-v6", + "auto-dnssec", + "update-check-ksk" + ], + "modified": [ + { + "option": "update-policy", + "old_definition": "( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesubject ) [ ] ", + "new_definition": "( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ ] " + }, + { + "option": "also-notify", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + }, + { + "option": "parental-agents", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + }, + { + "option": "forwarders", + "old_definition": "[ port ] { ( | ) [ port ]", + "new_definition": "[ port ] [ tls ] { ( | ) [ port ] [ tls ]" + } + ], + "deprecated_new": [ + "max-zone-ttl" + ], + "options1_count": 63, + "options2_count": 62 + }, + "redirect.zoneopt": { + "file": "redirect.zoneopt", + "added": [], + "removed": [], + "modified": [ + { + "option": "primaries", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + } + ], + "deprecated_new": [ + "max-zone-ttl" + ], + "options1_count": 14, + "options2_count": 14 + }, + "secondary.zoneopt": { + "file": "secondary.zoneopt", + "added": [ + "checkds", + "min-transfer-rate-in", + "notify-defer" + ], + "removed": [ + "alt-transfer-source", + "alt-transfer-source-v6", + "auto-dnssec", + "use-alt-transfer-source" + ], + "modified": [ + { + "option": "also-notify", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + }, + { + "option": "parental-agents", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + }, + { + "option": "forwarders", + "old_definition": "[ port ] { ( | ) [ port ]", + "new_definition": "[ port ] [ tls ] { ( | ) [ port ] [ tls ]" + }, + { + "option": "primaries", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + } + ], + "deprecated_new": [], + "options1_count": 66, + "options2_count": 65 + }, + "static-stub.zoneopt": { + "file": "static-stub.zoneopt", + "added": [], + "removed": [], + "modified": [ + { + "option": "forwarders", + "old_definition": "[ port ] { ( | ) [ port ]", + "new_definition": "[ port ] [ tls ] { ( | ) [ port ] [ tls ]" + } + ], + "deprecated_new": [], + "options1_count": 12, + "options2_count": 12 + }, + "stub.zoneopt": { + "file": "stub.zoneopt", + "added": [ + "min-transfer-rate-in" + ], + "removed": [ + "delegation-only", + "use-alt-transfer-source" + ], + "modified": [ + { + "option": "forwarders", + "old_definition": "[ port ] { ( | ) [ port ]", + "new_definition": "[ port ] [ tls ] { ( | ) [ port ] [ tls ]" + }, + { + "option": "primaries", + "old_definition": "[ port ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]", + "new_definition": "[ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]" + } + ], + "deprecated_new": [], + "options1_count": 28, + "options2_count": 27 + }, + "delegation-only.zoneopt": { + "file": "delegation-only.zoneopt", + "added": [], + "removed": [ + "type", + "zone" + ], + "modified": [], + "deprecated_new": [], + "options1_count": 2, + "options2_count": 0 + }, + "rndc.grammar": { + "file": "rndc.grammar", + "added": [], + "removed": [], + "modified": [], + "deprecated_new": [], + "options1_count": 14, + "options2_count": 14 + } +} \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml index 26a4665..589c245 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -16,10 +16,8 @@ - "{{ bind9_cfgdir }}" - "{{ bind9_working_directory }}" - "{{ bind9_libdir }}" - dest: "{{ - bind9_backup_dir + '/bind9-config-' + - ansible_facts.date_time.iso8601_basic_short + '.tar.gz' }}" + dest: "{{ bind9_backup_dir + '/bind9-config-' + ansible_facts.date_time.iso8601_basic_short + '.tar.gz' }}" owner: root group: root - mode: '0640' + mode: "0640" when: bind9_backup_config is defined and bind9_backup_config diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml index 69ccf1b..cb79629 100644 --- a/meta/argument_specs.yml +++ b/meta/argument_specs.yml @@ -2,13 +2,16 @@ argument_specs: main: short_description: The main entry point for the bind9 role. + description: + - Configures BIND9 DNS server on Debian-based systems. + - "Supported BIND9 versions: 9.18.x (LTS), 9.20+ (feature releases)" + - Version detection is automatic at runtime. options: bind9_config: type: list elements: dict description: - - A list of configuration dictionaries that are merged to - produce the final configuration. + - A list of configuration dictionaries that are merged to produce the final configuration. - Each element must have a 'name' key (filename). bind9_default_config: type: list @@ -54,3 +57,10 @@ argument_specs: bind9_backup_dir: type: str description: Directory for backups. + bind9_version: + type: str + description: + - BIND9 version detected at runtime (read-only, set automatically). + - "Format: X.Y.Z (e.g., 9.18.44, 9.20.18)" + - Used by templates to apply version-specific configurations. + - Users should not set this variable directly. diff --git a/molecule/bind9-20/README.md b/molecule/bind9-20/README.md new file mode 100644 index 0000000..c910fcc --- /dev/null +++ b/molecule/bind9-20/README.md @@ -0,0 +1,108 @@ +# BIND9 9.20 Molecule Scenario + +This Molecule scenario validates the ansible-bind9-role with BIND9 9.20 and later feature releases. + +## Purpose + +- Tests role compatibility with BIND9 9.20+ which includes 44 breaking changes from 9.18.x +- Validates version-specific templates and configurations +- Ensures configuration syntax is correct for newer BIND9 versions +- Documents 9.20-specific configuration patterns + +## Platform + +- **Base Image**: Ubuntu 24.04 LTS (docker.io/library/ubuntu:24.04) +- **BIND9 Version**: 9.20.x or later (as available in Ubuntu 24.04 repositories) + +## Notable BIND9 9.20 Changes + +Key breaking changes in this scenario: + +1. **Automatic Options**: The following options are automatically enabled in 9.20 and should not be configured: + - `glue-cache` - Always enabled + - `keep-response-order` - Always enabled + - `reuse` - Always enabled + - `recursion-enabled` - Always enabled + +2. **Removed Options**: These options are no longer supported in 9.20: + - `alt-transfer-source` - Use TLS instead + - `alt-transfer-source-v6` - Use TLS instead + - `auto-dnssec` - DNSSEC management is automatic + - `dsc` - Use TLS configuration instead + - `gssapi-credential` - Use TSIG + TLS instead + - `heartbeat-interval` - Zone transfer monitoring changed + - `lock-file` - OS-level locking is used + - `root-delegation-only` - Use zone constraints instead + +3. **Enhanced Features**: + - Improved TLS/DoT support for zone transfers + - Native DNSSEC management + - Better resolver behavior and retry logic + - Native HTTP/HTTPS server capabilities + +## Configuration Features Tested + +- **DNS Forwarding**: Forward zones with TLS-based forwarders (DoT) +- **Query Logging**: Detailed query and response logging +- **DNSTAP**: DNS packet capture for forensics +- **TLS Configuration**: Modern TLS configurations for zone transfers +- **Recursion**: Proper recursion configuration with ACLs +- **DNSSEC Validation**: Modern DNSSEC validation approach + +## Testing + +To run this scenario: + +```bash +# Test with this specific scenario +cd /path/to/ansible-bind9-role +molecule test -s bind9-20 + +# Or specific steps +molecule create -s bind9-20 +molecule converge -s bind9-20 +molecule verify -s bind9-20 +molecule destroy -s bind9-20 +``` + +## Expected Results + +- BIND9 service starts successfully +- Configuration files are generated without errors +- DNS forwarding works correctly +- Named-checkconf validates the configuration +- All log channels are operational +- TLS connections are established for forwarders + +## Troubleshooting + +### BIND9 Package Not Available + +If BIND9 9.20 is not available in Ubuntu 24.04 repositories, you may need to: + +1. Build from source using the upstream ISC BIND9 repository +2. Use a different base image with more recent BIND9 packages +3. Add a custom APT repository with backported packages + +### Configuration Syntax Errors + +Review `/etc/bind/named.conf` using: + +```bash +named-checkconf /etc/bind/named.conf +``` + +Check logs at `/var/log/named/default.log` for specific error messages. + +## Future Updates + +- [ ] Add support for BIND9 9.20 DNS-over-HTTPS (DoH) +- [ ] Test with BIND9 9.22+ when released +- [ ] Validate performance improvements +- [ ] Test clustering/replication features + +## References + +- [BIND9 Documentation](https://bind9.readthedocs.io/) +- [BIND9 9.20 Release Notes](https://www.isc.org/bind/) +- [DNS-over-TLS (DoT) RFC 7858](https://tools.ietf.org/html/rfc7858) diff --git a/molecule/bind9-20/collections.yml b/molecule/bind9-20/collections.yml new file mode 100644 index 0000000..a6b0fd8 --- /dev/null +++ b/molecule/bind9-20/collections.yml @@ -0,0 +1,4 @@ +--- +collections: + - ansible.posix + - community.general diff --git a/molecule/bind9-20/converge.yml b/molecule/bind9-20/converge.yml new file mode 100644 index 0000000..113daa4 --- /dev/null +++ b/molecule/bind9-20/converge.yml @@ -0,0 +1,122 @@ +--- +- name: Converge + hosts: all + tasks: + - name: Create log directory for BIND + ansible.builtin.file: + path: /var/log/named + state: directory + mode: '0755' + owner: bind + group: bind + + - name: Include bind9 role + ansible.builtin.include_role: + name: ../../../ansible-bind9-role # noqa: role-name[path] + vars: + bind9_backup_config: false + # BIND9 9.20+ configuration with version-specific options + bind9_host_config: + - name: named.conf.options + options: + directory: "{{ bind9_working_directory }}" + recursion: true + allow_query: + - any + allow_recursion: + - 10.0.0.0/8 + - 192.168.0.0/16 + - 172.16.0.0/12 + - localhost + - localnets + forwarders: + - address: 91.239.100.100 + tls: censurfridns-anycast + - address: 89.233.43.71 + tls: censurfridns-unicast + forward: first + dnssec_validation: auto + dnstap: + - type: auth + - type: resolver + log: query + - type: client + log: response + dnstap_output: + output_type: file + output_file: /var/log/named/dnstap.log + size: 20m + versions: 3 + suffix: increment + dnstap_identity: dns-server-01 + dnstap_version: 9.20 + # Note: BIND9 9.20 automatically enables glue-cache, keep-response-order, reuse + # These options are removed in 9.20 and should not be configured + # Removed options (9.18 compatibility note): + # - alt_transfer_source (use TLS instead) + # - auto_dnssec (automatic in 9.20) + # - glue_cache (always enabled in 9.20) + logging: + channels: + - name: default_log + file: + name: /var/log/named/default.log + severity: info + print_time: true + print_severity: true + print_category: true + - name: security_log + file: + name: /var/log/named/security.log + severity: dynamic + print_time: true + print_severity: true + print_category: true + - name: query_log + file: + name: /var/log/named/queries.log + versions: 5 + size: 10m + severity: info + print_time: true + - name: dnssec_log + file: + name: /var/log/named/dnssec.log + severity: debug + print_time: true + print_severity: true + - name: rate_limit_log + syslog: daemon + severity: warning + categories: + - name: default + channels: + - default_log + - name: general + channels: + - default_log + - name: security + channels: + - security_log + - name: queries + channels: + - query_log + - name: dnssec + channels: + - dnssec_log + - name: rate-limit + channels: + - rate_limit_log + - name: named.conf.local + tls: + - name: censurfridns-anycast + remote_hostname: anycast.uncensoreddns.org + - name: censurfridns-unicast + remote_hostname: unicast.uncensoreddns.org + zones: + - name: example.internal + type: forward + forward: only + forwarders: + - 10.0.0.53 + - 10.0.0.54 diff --git a/molecule/bind9-20/molecule.yml b/molecule/bind9-20/molecule.yml new file mode 100644 index 0000000..c469bbe --- /dev/null +++ b/molecule/bind9-20/molecule.yml @@ -0,0 +1,22 @@ +--- +# Molecule scenario for BIND9 9.20+ support validation +# This scenario tests the role with BIND9 9.20 and later feature releases +# Note: May require ubuntu:24.04 or Debian 13 (Trixie) for 9.20 package availability + +driver: + name: podman +platforms: + - name: ubuntu-2404-bind920 + image: docker.io/library/ubuntu:24.04 + command: /lib/systemd/systemd + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host +provisioner: + name: ansible + config_options: + defaults: + ALLOW_BROKEN_CONDITIONALS: true +verifier: + name: ansible diff --git a/molecule/bind9-20/prepare.yml b/molecule/bind9-20/prepare.yml new file mode 100644 index 0000000..fdb0b40 --- /dev/null +++ b/molecule/bind9-20/prepare.yml @@ -0,0 +1,14 @@ +--- +- name: Prepare + hosts: all + tasks: + - name: Update package cache + ansible.builtin.apt: + update_cache: true + + - name: Install DNS query tools (dnsutils) + ansible.builtin.apt: + name: + - dnsutils + - bind9-doc + state: present diff --git a/molecule/bind9-20/verify.yml b/molecule/bind9-20/verify.yml new file mode 100644 index 0000000..32a9b18 --- /dev/null +++ b/molecule/bind9-20/verify.yml @@ -0,0 +1,120 @@ +--- +- name: Verify + hosts: all + gather_facts: true + tasks: + - name: Check that BIND9 is installed + ansible.builtin.package: + name: bind9 + state: present + check_mode: true + register: __bind9_package_check + failed_when: __bind9_package_check is changed + + - name: Check that BIND9 service is running + ansible.builtin.service: + name: named + state: started + enabled: true + check_mode: true + register: __bind9_service_check + failed_when: __bind9_service_check is changed + + - name: Check that BIND9 version is 9.20 or later + ansible.builtin.command: + cmd: named -v + register: __bind9_version_check + changed_when: false + failed_when: false + + - name: Display BIND9 version + ansible.builtin.debug: + msg: "BIND9 version: {{ __bind9_version_check.stdout }}" + + - name: Check that named.conf.options exists + ansible.builtin.stat: + path: /etc/bind/named.conf.options + register: __options_file + failed_when: not __options_file.stat.exists + + - name: Check that named.conf.local exists + ansible.builtin.stat: + path: /etc/bind/named.conf.local + register: __local_file + failed_when: not __local_file.stat.exists + + - name: Read named.conf.options content + ansible.builtin.slurp: + path: /etc/bind/named.conf.options + register: __options_content + + - name: Verify forwarders are configured in options + ansible.builtin.assert: + that: + - "'forwarders' in __options_decoded" + - "'91.239.100.100' in __options_decoded" + - "'forward first' in __options_decoded" + fail_msg: Forwarders not properly configured in named.conf.options + vars: + __options_decoded: "{{ __options_content.content | b64decode }}" + + - name: Read named.conf.local content + ansible.builtin.slurp: + path: /etc/bind/named.conf.local + register: __local_content + + - name: Verify forward zone is configured + ansible.builtin.assert: + that: + - "'zone \"example.internal\"' in __local_decoded" + - "'type forward' in __local_decoded" + - "'forward only' in __local_decoded" + fail_msg: Forward zone not properly configured in named.conf.local + vars: + __local_decoded: "{{ __local_content.content | b64decode }}" + + - name: Test DNS resolution using localhost + ansible.builtin.command: + cmd: dig @localhost google.com +short + register: __dns_query + changed_when: false + failed_when: __dns_query.rc != 0 + + - name: Verify DNS query returned results + ansible.builtin.assert: + that: + - __dns_query.stdout_lines | length > 0 + fail_msg: DNS forwarding is not working + + - name: Validate configuration syntax with named-checkconf + ansible.builtin.command: + cmd: named-checkconf /etc/bind/named.conf + register: __named_checkconf + changed_when: false + failed_when: __named_checkconf.rc != 0 + + - name: Check BIND logs for errors + ansible.builtin.command: + cmd: tail -30 /var/log/named/default.log + register: __bind_logs + changed_when: false + + - name: Display BIND logs + ansible.builtin.debug: + msg: "BIND logs:\n{{ __bind_logs.stdout }}" + + - name: Verify no critical errors in logs + ansible.builtin.shell: | + set -o pipefail + if grep -i "error" /var/log/named/default.log | grep -v "error reporting" > /dev/null; then + exit 1 + fi + changed_when: false + failed_when: false + register: __error_check + + - name: Assert no critical errors found + ansible.builtin.assert: + that: + - __error_check.rc == 0 + fail_msg: Found critical errors in BIND logs diff --git a/scripts/compare_bind_versions.py b/scripts/compare_bind_versions.py new file mode 100644 index 0000000..5f214b4 --- /dev/null +++ b/scripts/compare_bind_versions.py @@ -0,0 +1,390 @@ +#!/usr/bin/env python3 +""" +Compare BIND9 grammar files between versions to identify breaking changes. + +This script compares grammar files from two BIND9 versions and generates +a comprehensive report of: +- Removed options (breaking changes) +- Added options (new features) +- Modified option syntax +- Deprecated options + +Usage: + python scripts/compare_bind_versions.py \\ + --version1-dir bind9-grammar/upstream/v9.18.44 \\ + --version2-dir bind9-grammar/upstream/v9.20.18 \\ + --output docs/BIND_VERSION_DIFFERENCES.md +""" + +import argparse +import json +import sys +from pathlib import Path +from typing import Dict, List, Set, Tuple +import re + + +class GrammarComparator: + """Compare BIND9 grammar files between versions.""" + + def __init__(self, version1_dir: Path, version2_dir: Path): + """ + Initialize comparator with two version directories. + + Args: + version1_dir: Path to first version's grammar files + version2_dir: Path to second version's grammar files + """ + self.version1_dir = version1_dir + self.version2_dir = version2_dir + self.version1_name = version1_dir.name + self.version2_name = version2_dir.name + + def load_grammar_file(self, file_path: Path) -> Dict: + """Load and parse a grammar file.""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Parse grammar file into structured data + options = self._parse_grammar(content) + return options + except FileNotFoundError: + return {} + + def _parse_grammar(self, content: str) -> Dict[str, str]: + """ + Parse grammar content into a dictionary of options. + + This is a simplified parser that extracts top-level keywords + and their definitions. + """ + options = {} + lines = content.split('\n') + + for line in lines: + line = line.strip() + if not line or line.startswith('#') or line.startswith('//'): + continue + + # Extract keyword and its definition + # Pattern: keyword ; or keyword { ... }; + match = re.match(r'^([a-z0-9-]+)\s+(.+?)(?:;|$)', line) + if match: + keyword = match.group(1) + definition = match.group(2).strip() + + # Extract flags from comments + flags = [] + if '// may occur multiple times' in line: + flags.append('may occur multiple times') + if '// deprecated' in line: + flags.append('deprecated') + if '// obsolete' in line: + flags.append('obsolete') + if '// not configured' in line: + flags.append('not configured') + if '// test only' in line: + flags.append('test only') + if '// experimental' in line: + flags.append('experimental') + + options[keyword] = { + 'definition': definition, + 'flags': flags, + 'raw_line': line + } + + return options + + def compare_files(self, filename: str) -> Dict: + """ + Compare a specific grammar file between two versions. + + Returns: + Dict with added, removed, modified, and deprecated options + """ + file1 = self.version1_dir / 'grammar' / filename + file2 = self.version2_dir / 'grammar' / filename + + options1 = self.load_grammar_file(file1) + options2 = self.load_grammar_file(file2) + + keys1 = set(options1.keys()) + keys2 = set(options2.keys()) + + # Identify changes + added = keys2 - keys1 + removed = keys1 - keys2 + common = keys1 & keys2 + + modified = [] + deprecated_new = [] + + for key in common: + opt1 = options1[key] + opt2 = options2[key] + + # Check if definition changed + if opt1['definition'] != opt2['definition']: + modified.append({ + 'option': key, + 'old_definition': opt1['definition'], + 'new_definition': opt2['definition'] + }) + + # Check if newly deprecated + if 'deprecated' not in opt1['flags'] and 'deprecated' in opt2['flags']: + deprecated_new.append(key) + + return { + 'file': filename, + 'added': sorted(added), + 'removed': sorted(removed), + 'modified': modified, + 'deprecated_new': deprecated_new, + 'options1_count': len(options1), + 'options2_count': len(options2) + } + + def compare_all(self) -> Dict: + """Compare all grammar files between versions.""" + # List of grammar files to compare + grammar_files = [ + 'options', + 'forward.zoneopt', + 'hint.zoneopt', + 'in-view.zoneopt', + 'mirror.zoneopt', + 'primary.zoneopt', + 'redirect.zoneopt', + 'secondary.zoneopt', + 'static-stub.zoneopt', + 'stub.zoneopt', + 'delegation-only.zoneopt', + 'rndc.grammar', + ] + + results = {} + for filename in grammar_files: + result = self.compare_files(filename) + results[filename] = result + + return results + + def generate_markdown_report(self, results: Dict) -> str: + """Generate a Markdown report from comparison results.""" + lines = [] + lines.append(f"# BIND9 Version Differences: {self.version1_name} vs {self.version2_name}") + lines.append("") + lines.append(f"This document compares BIND9 configuration grammar between {self.version1_name} and {self.version2_name}.") + lines.append("") + lines.append("Generated automatically by `scripts/compare_bind_versions.py`.") + lines.append("") + + # Summary + lines.append("## Summary") + lines.append("") + + total_added = sum(len(r['added']) for r in results.values()) + total_removed = sum(len(r['removed']) for r in results.values()) + total_modified = sum(len(r['modified']) for r in results.values()) + total_deprecated = sum(len(r['deprecated_new']) for r in results.values()) + + lines.append(f"- **New Options**: {total_added}") + lines.append(f"- **Removed Options**: {total_removed} ⚠️") + lines.append(f"- **Modified Options**: {total_modified}") + lines.append(f"- **Newly Deprecated**: {total_deprecated}") + lines.append("") + + # Breaking Changes + if total_removed > 0: + lines.append("## ⚠️ Breaking Changes") + lines.append("") + lines.append(f"The following options were removed in {self.version2_name} and will cause configuration errors:") + lines.append("") + + for filename, result in results.items(): + if result['removed']: + lines.append(f"### {filename}") + lines.append("") + for option in result['removed']: + lines.append(f"- `{option}`") + lines.append("") + + # New Features + if total_added > 0: + lines.append("## ✨ New Features") + lines.append("") + lines.append(f"The following options were added in {self.version2_name}:") + lines.append("") + + for filename, result in results.items(): + if result['added']: + lines.append(f"### {filename}") + lines.append("") + for option in result['added']: + lines.append(f"- `{option}`") + lines.append("") + + # Modified Options + if total_modified > 0: + lines.append("## 🔧 Modified Options") + lines.append("") + lines.append(f"The following options have syntax changes in {self.version2_name}:") + lines.append("") + + for filename, result in results.items(): + if result['modified']: + lines.append(f"### {filename}") + lines.append("") + for mod in result['modified']: + lines.append(f"#### `{mod['option']}`") + lines.append("") + lines.append(f"**{self.version1_name}**:") + lines.append(f"```") + lines.append(f"{mod['old_definition']}") + lines.append(f"```") + lines.append("") + lines.append(f"**{self.version2_name}**:") + lines.append(f"```") + lines.append(f"{mod['new_definition']}") + lines.append(f"```") + lines.append("") + + # Deprecated Options + if total_deprecated > 0: + lines.append("## 📋 Newly Deprecated Options") + lines.append("") + lines.append(f"The following options were marked as deprecated in {self.version2_name}:") + lines.append("") + + for filename, result in results.items(): + if result['deprecated_new']: + lines.append(f"### {filename}") + lines.append("") + for option in result['deprecated_new']: + lines.append(f"- `{option}`") + lines.append("") + + # File-by-File Comparison + lines.append("## Detailed File-by-File Comparison") + lines.append("") + + for filename, result in results.items(): + lines.append(f"### {filename}") + lines.append("") + lines.append(f"- {self.version1_name}: {result['options1_count']} options") + lines.append(f"- {self.version2_name}: {result['options2_count']} options") + lines.append(f"- Added: {len(result['added'])}") + lines.append(f"- Removed: {len(result['removed'])}") + lines.append(f"- Modified: {len(result['modified'])}") + lines.append("") + + # Migration Guide + if total_removed > 0 or total_deprecated > 0: + lines.append("## Migration Guide") + lines.append("") + lines.append(f"### Migrating from {self.version1_name} to {self.version2_name}") + lines.append("") + + if total_removed > 0: + lines.append("1. **Remove unsupported options** from your configuration") + lines.append(" - Review the Breaking Changes section above") + lines.append(" - Check if there are replacement options") + lines.append("") + + if total_deprecated > 0: + lines.append("2. **Plan for deprecated options**") + lines.append(" - These options still work but may be removed in future versions") + lines.append(" - Start planning migration to recommended alternatives") + lines.append("") + + lines.append("3. **Test your configuration**") + lines.append(" - Use `named-checkconf` to validate syntax") + lines.append(" - Test in a development environment before production") + lines.append("") + + return '\n'.join(lines) + + +def main(): + """Main entry point.""" + parser = argparse.ArgumentParser( + description="Compare BIND9 grammar files between versions" + ) + parser.add_argument( + "--version1-dir", + type=Path, + required=True, + help="Directory containing first version's grammar files" + ) + parser.add_argument( + "--version2-dir", + type=Path, + required=True, + help="Directory containing second version's grammar files" + ) + parser.add_argument( + "--output", + type=Path, + default=Path("docs/BIND_VERSION_DIFFERENCES.md"), + help="Output file for Markdown report" + ) + parser.add_argument( + "--json", + type=Path, + help="Also output raw comparison as JSON" + ) + + args = parser.parse_args() + + # Validate directories + if not args.version1_dir.exists(): + print(f"Error: {args.version1_dir} does not exist", file=sys.stderr) + sys.exit(1) + + if not args.version2_dir.exists(): + print(f"Error: {args.version2_dir} does not exist", file=sys.stderr) + sys.exit(1) + + # Perform comparison + print(f"Comparing BIND9 versions:") + print(f" Version 1: {args.version1_dir.name}") + print(f" Version 2: {args.version2_dir.name}") + + comparator = GrammarComparator(args.version1_dir, args.version2_dir) + results = comparator.compare_all() + + # Generate and save Markdown report + report = comparator.generate_markdown_report(results) + + args.output.parent.mkdir(parents=True, exist_ok=True) + with open(args.output, 'w', encoding='utf-8') as f: + f.write(report) + + print(f"✓ Markdown report saved to: {args.output}") + + # Save JSON if requested + if args.json: + args.json.parent.mkdir(parents=True, exist_ok=True) + with open(args.json, 'w', encoding='utf-8') as f: + json.dump(results, f, indent=2) + print(f"✓ JSON comparison saved to: {args.json}") + + # Print summary + total_added = sum(len(r['added']) for r in results.values()) + total_removed = sum(len(r['removed']) for r in results.values()) + total_modified = sum(len(r['modified']) for r in results.values()) + + print(f"\nComparison Summary:") + print(f" Added options: {total_added}") + print(f" Removed options: {total_removed}") + print(f" Modified options: {total_modified}") + + if total_removed > 0: + print(f"\n⚠️ Warning: {total_removed} breaking changes detected!") + + +if __name__ == "__main__": + main() diff --git a/scripts/fetch_bind_grammar.py b/scripts/fetch_bind_grammar.py new file mode 100644 index 0000000..fcbbe87 --- /dev/null +++ b/scripts/fetch_bind_grammar.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +""" +Fetch BIND9 grammar files from Gitea mirror repository for version comparison. + +This script uses the Gitea MCP tools to fetch grammar files from the official +BIND9 mirror at git.valid.dk/Mirrors/bind9 for specified version tags. +""" + +import argparse +import json +import os +import sys +from pathlib import Path +from typing import Dict, List + + +# Grammar files to fetch from doc/misc/ +GRAMMAR_FILES = [ + "options", + "forward.zoneopt", + "hint.zoneopt", + "in-view.zoneopt", + "mirror.zoneopt", + "primary.zoneopt", + "redirect.zoneopt", + "secondary.zoneopt", + "static-stub.zoneopt", + "stub.zoneopt", + "delegation-only.zoneopt", + "rndc.grammar", +] + +# Support files +SUPPORT_FILES = [ + "parsegrammar.py", + "checkgrammar.py", +] + + +def fetch_file_content(owner: str, repo: str, ref: str, file_path: str) -> str: + """ + Fetch file content from Gitea repository. + + This would use mcp_gitea-mcp_get_file_content in the actual MCP environment. + For standalone usage, returns placeholder. + """ + # In MCP environment, this would call: + # mcp_gitea-mcp_get_file_content(owner=owner, repo=repo, ref=ref, filePath=file_path) + print(f"Would fetch: {owner}/{repo}@{ref}:{file_path}") + return "" + + +def save_grammar_file(content: str, version: str, filename: str, output_dir: Path): + """Save fetched grammar file to local directory.""" + version_dir = output_dir / version / "grammar" + version_dir.mkdir(parents=True, exist_ok=True) + + file_path = version_dir / filename + with open(file_path, 'w', encoding='utf-8') as f: + f.write(content) + + print(f"Saved: {file_path}") + + +def fetch_version_grammars(owner: str, repo: str, tag: str, output_dir: Path): + """Fetch all grammar files for a specific version tag.""" + print(f"\n=== Fetching grammar files for {tag} ===") + + # Create metadata + metadata = { + "version": tag, + "repository": f"{owner}/{repo}", + "files": [], + } + + # Fetch grammar files + for grammar_file in GRAMMAR_FILES: + try: + file_path = f"doc/misc/{grammar_file}" + content = fetch_file_content(owner, repo, tag, file_path) + + if content: + save_grammar_file(content, tag, grammar_file, output_dir) + metadata["files"].append({ + "name": grammar_file, + "path": file_path, + "type": "grammar" + }) + except Exception as e: + print(f"Warning: Could not fetch {grammar_file}: {e}") + + # Fetch support files + for support_file in SUPPORT_FILES: + try: + file_path = f"doc/misc/{support_file}" + content = fetch_file_content(owner, repo, tag, file_path) + + if content: + save_grammar_file(content, tag, support_file, output_dir) + metadata["files"].append({ + "name": support_file, + "path": file_path, + "type": "support" + }) + except Exception as e: + print(f"Warning: Could not fetch {support_file}: {e}") + + # Save metadata + metadata_file = output_dir / tag / "metadata.json" + with open(metadata_file, 'w', encoding='utf-8') as f: + json.dump(metadata, f, indent=2) + + print(f"Metadata saved: {metadata_file}") + return metadata + + +def main(): + """Main entry point.""" + parser = argparse.ArgumentParser( + description="Fetch BIND9 grammar files from Gitea mirror" + ) + parser.add_argument( + "--owner", + default="Mirrors", + help="Repository owner (default: Mirrors)" + ) + parser.add_argument( + "--repo", + default="bind9", + help="Repository name (default: bind9)" + ) + parser.add_argument( + "--tags", + nargs="+", + default=["v9.18.44", "v9.20.18"], + help="Version tags to fetch (default: v9.18.44 v9.20.18)" + ) + parser.add_argument( + "--output-dir", + type=Path, + default=Path("bind9-grammar/upstream"), + help="Output directory for grammar files" + ) + + args = parser.parse_args() + + print("BIND9 Grammar Fetcher") + print("=" * 60) + print(f"Repository: {args.owner}/{args.repo}") + print(f"Tags: {', '.join(args.tags)}") + print(f"Output: {args.output_dir}") + + # Fetch grammars for each version + results = {} + for tag in args.tags: + try: + metadata = fetch_version_grammars( + args.owner, + args.repo, + tag, + args.output_dir + ) + results[tag] = metadata + except Exception as e: + print(f"Error fetching {tag}: {e}") + sys.exit(1) + + # Save overall summary + summary_file = args.output_dir / "fetch_summary.json" + with open(summary_file, 'w', encoding='utf-8') as f: + json.dump(results, f, indent=2) + + print(f"\n=== Fetch complete ===") + print(f"Summary: {summary_file}") + print(f"Fetched {len(results)} versions") + + +if __name__ == "__main__": + main() diff --git a/scripts/fetch_bind_grammar_mcp.py b/scripts/fetch_bind_grammar_mcp.py new file mode 100644 index 0000000..d68a517 --- /dev/null +++ b/scripts/fetch_bind_grammar_mcp.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +""" +Fetch BIND9 grammar files using Gitea MCP integration. + +This script demonstrates how to use mcp_gitea-mcp tools to fetch grammar files. +Since we can't directly call MCP tools from Python, this serves as documentation +for the manual fetching process that should be done through the MCP interface. + +Usage: + The actual fetching should be done through MCP tool calls: + + 1. List available tags: + mcp_gitea-mcp_list_tags(owner="Mirrors", repo="bind9") + + 2. Get directory listing: + mcp_gitea-mcp_get_dir_content(owner="Mirrors", repo="bind9", + ref="v9.18.44", filePath="doc/misc") + + 3. Fetch each grammar file: + mcp_gitea-mcp_get_file_content(owner="Mirrors", repo="bind9", + ref="v9.18.44", + filePath="doc/misc/options") +""" + +import json +from pathlib import Path +from typing import Dict, List + +# Target versions +VERSIONS = { + "9.18": "v9.18.44", + "9.20": "v9.20.18", +} + +# Grammar files to fetch +GRAMMAR_FILES = [ + "options", + "forward.zoneopt", + "hint.zoneopt", + "in-view.zoneopt", + "mirror.zoneopt", + "primary.zoneopt", + "redirect.zoneopt", + "secondary.zoneopt", + "static-stub.zoneopt", + "stub.zoneopt", + "delegation-only.zoneopt", + "rndc.grammar", +] + +SUPPORT_FILES = [ + "parsegrammar.py", + "checkgrammar.py", +] + + +def generate_fetch_commands() -> List[Dict]: + """Generate MCP tool call commands for fetching grammar files.""" + commands = [] + + for version_name, tag in VERSIONS.items(): + # List directory command + commands.append({ + "tool": "mcp_gitea-mcp_get_dir_content", + "params": { + "owner": "Mirrors", + "repo": "bind9", + "ref": tag, + "filePath": "doc/misc" + }, + "description": f"List grammar files for {version_name} ({tag})" + }) + + # File fetch commands + for grammar_file in GRAMMAR_FILES + SUPPORT_FILES: + commands.append({ + "tool": "mcp_gitea-mcp_get_file_content", + "params": { + "owner": "Mirrors", + "repo": "bind9", + "ref": tag, + "filePath": f"doc/misc/{grammar_file}" + }, + "save_to": f"bind9-grammar/upstream/{tag}/grammar/{grammar_file}", + "description": f"Fetch {grammar_file} for {version_name}" + }) + + return commands + + +def save_file_structure() -> Dict: + """Generate expected file structure after fetching.""" + structure = { + "bind9-grammar": { + "upstream": {} + } + } + + for version_name, tag in VERSIONS.items(): + structure["bind9-grammar"]["upstream"][tag] = { + "grammar": { + "files": GRAMMAR_FILES + SUPPORT_FILES + }, + "metadata.json": { + "version": tag, + "version_name": version_name, + "repository": "Mirrors/bind9", + "fetched_files": len(GRAMMAR_FILES) + len(SUPPORT_FILES) + } + } + + return structure + + +def main(): + """Generate instructions and commands for grammar fetching.""" + print("=" * 70) + print("BIND9 Grammar Fetcher - MCP Integration Guide") + print("=" * 70) + + print("\nTarget Versions:") + for version_name, tag in VERSIONS.items(): + print(f" - BIND {version_name}: {tag}") + + print(f"\nFiles to fetch per version: {len(GRAMMAR_FILES)} grammar files + {len(SUPPORT_FILES)} support files") + + print("\n" + "=" * 70) + print("MCP TOOL CALL SEQUENCE") + print("=" * 70) + + commands = generate_fetch_commands() + + for i, cmd in enumerate(commands, 1): + print(f"\n[{i}/{len(commands)}] {cmd['description']}") + print(f"Tool: {cmd['tool']}") + print(f"Parameters:") + for key, value in cmd['params'].items(): + print(f" - {key}: {value}") + if 'save_to' in cmd: + print(f"Save to: {cmd['save_to']}") + + print("\n" + "=" * 70) + print("EXPECTED FILE STRUCTURE") + print("=" * 70) + + structure = save_file_structure() + print(json.dumps(structure, indent=2)) + + # Save command list + output_dir = Path("bind9-grammar/upstream") + output_dir.mkdir(parents=True, exist_ok=True) + + commands_file = output_dir / "fetch_commands.json" + with open(commands_file, 'w') as f: + json.dump(commands, f, indent=2) + + print(f"\nCommand list saved to: {commands_file}") + print("\nNote: These commands should be executed through the MCP interface,") + print(" not directly from this Python script.") + + +if __name__ == "__main__": + main() diff --git a/scripts/process_mcp_result.py b/scripts/process_mcp_result.py new file mode 100644 index 0000000..9f31f40 --- /dev/null +++ b/scripts/process_mcp_result.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +""" +Fetch BIND9 grammar files using Gitea MCP tools. +This script must be run from an environment where MCP tools are available. +""" + +import base64 +import json +import sys +from pathlib import Path + +# Files to fetch +GRAMMAR_FILES = [ + "options", + "forward.zoneopt", + "hint.zoneopt", + "in-view.zoneopt", + "mirror.zoneopt", + "primary.zoneopt", + "redirect.zoneopt", + "secondary.zoneopt", + "static-stub.zoneopt", + "stub.zoneopt", + "delegation-only.zoneopt", + "rndc.grammar", + "parsegrammar.py", + "checkgrammar.py", +] + +def save_file_from_mcp_result(result_json: dict, output_path: Path) -> bool: + """Save a file from MCP tool result JSON.""" + try: + if 'Result' in result_json and 'content' in result_json['Result']: + content_b64 = result_json['Result']['content'] + content = base64.b64decode(content_b64).decode('utf-8') + + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, 'w', encoding='utf-8') as f: + f.write(content) + + return True + return False + except Exception as e: + print(f"Error saving {output_path}: {e}", file=sys.stderr) + return False + +def main(): + """Process stdin JSON from MCP tool calls.""" + print("Reading MCP tool results from stdin...") + + # Read all input + input_data = sys.stdin.read() + + try: + result = json.loads(input_data) + + # Determine output path from result metadata + if 'Result' in result and 'name' in result['Result']: + filename = result['Result']['name'] + # Output path will be provided as command line argument + if len(sys.argv) > 1: + output_path = Path(sys.argv[1]) + if save_file_from_mcp_result(result, output_path): + print(f"✓ Saved: {output_path}") + sys.exit(0) + else: + print(f"✗ Failed to save: {output_path}", file=sys.stderr) + sys.exit(1) + + print("✗ Could not determine output path", file=sys.stderr) + sys.exit(1) + + except json.JSONDecodeError as e: + print(f"✗ Invalid JSON input: {e}", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/scripts/save_grammar_file.py b/scripts/save_grammar_file.py new file mode 100644 index 0000000..9b94305 --- /dev/null +++ b/scripts/save_grammar_file.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Helper script to save base64-encoded grammar file from MCP tool output.""" + +import base64 +import json +import sys +from pathlib import Path + +def main(): + if len(sys.argv) != 3: + print("Usage: save_grammar_file.py ") + sys.exit(1) + + json_file = Path(sys.argv[1]) + output_path = Path(sys.argv[2]) + + # Read JSON from MCP tool output + with open(json_file, 'r') as f: + data = json.load(f) + + # Extract and decode base64 content + if 'Result' in data and 'content' in data['Result']: + content_b64 = data['Result']['content'] + content = base64.b64decode(content_b64).decode('utf-8') + + # Save to output path + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, 'w', encoding='utf-8') as f: + f.write(content) + + print(f"✓ Saved: {output_path}") + else: + print(f"✗ Error: No content found in JSON", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/tasks/main.yml b/tasks/main.yml index cddd449..d6f2ed4 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -15,7 +15,7 @@ state: directory owner: root group: root - mode: '0750' + mode: "0750" when: bind9_backup_config is defined and bind9_backup_config | bool - name: Deploy and Validate Configuration @@ -33,9 +33,9 @@ remote_src: true owner: root group: bind - mode: '0640' + mode: "0640" changed_when: false - failed_when: false # It's okay if the file doesn't exist yet + failed_when: false # It's okay if the file doesn't exist yet loop: "{{ bind9_config }}" loop_control: label: "{{ item.name }}" @@ -46,11 +46,11 @@ dest: "{{ bind9_cfgdir }}/{{ item.name }}" owner: root group: bind - mode: '0640' + mode: "0640" loop: "{{ bind9_config }}" loop_control: label: "{{ item.name }}" - register: _template_result + register: bind9_template_result - name: Validate configuration using named-checkconf ansible.builtin.command: @@ -65,7 +65,7 @@ remote_src: true owner: root group: bind - mode: '0640' + mode: "0640" loop: "{{ bind9_config }}" loop_control: label: "{{ item.name }}"