Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
418 changes: 418 additions & 0 deletions docs/roadmaps/bind9-full-zone-config-support.md

Large diffs are not rendered by default.

19 changes: 16 additions & 3 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- **Enhanced Zone Configuration Support** - Full BIND9 zone option preservation
- Added 30+ new structured fields to `ZoneConfig` (notify, forwarders, DNSSEC, transfer control, etc.)
- Added 6 new enum types: `ForwarderSpec`, `NotifyMode`, `ForwardMode`, `AutoDnssecMode`, `CheckNamesMode`, `MasterfileFormat`
- Added `raw_options: HashMap<String, String>` catch-all for unknown BIND9 options
- Catch-all parser automatically preserves any unrecognized BIND9 zone options
- Full round-trip preservation: parse → modify → serialize with zero data loss
- Support for TSIG key references in `allow-update` via `allow_update_raw` field
- Comprehensive RNDC output parser using nom combinators
- Support for parsing `rndc showzone` output into structured ZoneConfig
- CIDR notation handling in IP address lists (e.g., `10.0.0.1/32`)
- Key-based `allow-update` directive parsing (key references ignored)
- Support for both modern (`primary`/`secondary`) and legacy (`master`/`slave`) BIND9 terminology
- Round-trip serialization: parse → modify → serialize → apply
- Zone modification via PATCH /api/v1/zones/{name} for `also-notify` and `allow-transfer`
- Zone modification via PATCH /api/v1/zones/{name} for `also-notify`, `allow-transfer`, and `allow-update`

### Changed
- **ZoneConfig Structure** - Enhanced with 30+ optional fields organized by category
- **Parser** - Now preserves all unknown options in `raw_options` HashMap
- **Serializer** - Extended to serialize all new fields and raw options
- Zone modification now uses `rndc showzone` instead of `rndc zonestatus` for full configuration retrieval
- RNDC errors now return 500 Internal Server Error (was 502 Bad Gateway)
- Raw RNDC error messages returned to clients (no wrapper text)

### Fixed
- `rndc modzone` now sends complete zone definition including type (was causing "zone type not specified" errors)
- Parser handles real-world BIND9 output with CIDR notation and TSIG keys
- PATCH operations now preserve key-based `allow-update` directives when modifying other fields
- Fixed double semicolon bug in serialization of raw directives

### Documentation
- Added comprehensive RNDC parser documentation in developer guide
- Added parser architecture diagrams and usage examples
- Documented CIDR stripping rationale and key-based ACL handling
- Created roadmap for rndc.conf parser implementation
- Created roadmap for BIND9 full zone configuration support
- Updated developer guide with enhanced ZoneConfig structure and capabilities
- Added 11 new tests for unknown option preservation and round-trip serialization

## [0.1.0] - 2025-12-03

Expand Down
162 changes: 145 additions & 17 deletions docs/src/developer-guide/rndc-parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,78 @@ Primary data structure representing a BIND9 zone configuration:

```rust
pub struct ZoneConfig {
pub zone_name: String, // Zone domain name
pub class: DnsClass, // IN, CH, or HS
pub zone_type: ZoneType, // Primary, Secondary, etc.
pub file: Option<String>, // Zone file path
pub primaries: Option<Vec<PrimarySpec>>, // Primary server IPs (for secondaries)
pub also_notify: Option<Vec<IpAddr>>, // Notify targets
pub allow_transfer: Option<Vec<IpAddr>>, // Transfer ACL
pub allow_update: Option<Vec<IpAddr>>, // Update ACL (IP-based only)
// Core fields
pub zone_name: String,
pub class: DnsClass,
pub zone_type: ZoneType,
pub file: Option<String>,

// Primary/Secondary options
pub primaries: Option<Vec<PrimarySpec>>,
pub also_notify: Option<Vec<IpAddr>>,
pub notify: Option<NotifyMode>,

// Access Control options
pub allow_query: Option<Vec<IpAddr>>,
pub allow_transfer: Option<Vec<IpAddr>>,
pub allow_update: Option<Vec<IpAddr>>,
pub allow_update_raw: Option<String>, // Raw directive for key-based updates
pub allow_update_forwarding: Option<Vec<IpAddr>>,
pub allow_notify: Option<Vec<IpAddr>>,

// Transfer Control options
pub max_transfer_time_in: Option<u32>,
pub max_transfer_time_out: Option<u32>,
pub transfer_source: Option<IpAddr>,
pub transfer_source_v6: Option<IpAddr>,
pub notify_source: Option<IpAddr>,
pub notify_source_v6: Option<IpAddr>,
// ... (and more transfer control options)

// Dynamic Update options
pub update_policy: Option<String>,
pub journal: Option<String>,
pub ixfr_from_differences: Option<bool>,

// DNSSEC options
pub inline_signing: Option<bool>,
pub auto_dnssec: Option<AutoDnssecMode>,
pub key_directory: Option<String>,
// ... (and more DNSSEC options)

// Forwarding options
pub forward: Option<ForwardMode>,
pub forwarders: Option<Vec<ForwarderSpec>>,

// Zone Maintenance options
pub check_names: Option<CheckNamesMode>,
pub check_mx: Option<CheckNamesMode>,
pub masterfile_format: Option<MasterfileFormat>,
pub max_zone_ttl: Option<u32>,

// Refresh/Retry options
pub max_refresh_time: Option<u32>,
pub min_refresh_time: Option<u32>,
pub max_retry_time: Option<u32>,
pub min_retry_time: Option<u32>,

// Miscellaneous options
pub multi_master: Option<bool>,
pub request_ixfr: Option<bool>,
pub request_expire: Option<bool>,

// Generic catch-all for unrecognized options
pub raw_options: HashMap<String, String>,
}
```

**Key Features:**

- **30+ Structured Fields**: Supports common BIND9 zone options with proper typing
- **Catch-All HashMap**: `raw_options` preserves unknown/custom BIND9 options
- **Full Round-Trip**: All options preserved during parse → modify → serialize cycle
- **Backward Compatible**: All new fields are `Option<T>`

### ZoneType

Supported zone types:
Expand Down Expand Up @@ -376,25 +437,92 @@ cargo test rndc_parser --lib -- --nocapture
cargo test test_parse_exact_production_output --lib
```

## Enhanced Features (v0.6.0+)

### Unknown Option Preservation

The parser now includes a catch-all mechanism that preserves all unknown BIND9 options:

```rust
let input = r#"zone "example.com" {
type primary;
file "/var/cache/bind/example.com.zone";
zone-statistics full;
check-names warn;
custom-option { custom value; };
};"#;

let config = parse_showzone(input)?;

// Unknown options preserved in raw_options HashMap
assert_eq!(config.raw_options.get("zone-statistics"), Some(&"full".to_string()));
assert_eq!(config.raw_options.get("check-names"), Some(&"warn".to_string()));
assert_eq!(config.raw_options.get("custom-option"), Some(&"{ custom value; }".to_string()));

// Serialization preserves all options
let serialized = config.to_rndc_block();
assert!(serialized.contains("zone-statistics full"));
assert!(serialized.contains("check-names warn"));
assert!(serialized.contains("custom-option { custom value; }"));
```

**Benefits:**

- **Future-Proof**: New BIND9 options automatically supported
- **No Data Loss**: Complete round-trip preservation
- **Custom Options**: Support for non-standard BIND9 configurations
- **Gradual Migration**: Add structured parsing for popular options over time

### Key-Based Access Control

Enhanced handling of TSIG key references in `allow-update`:

```rust
let input = r#"zone "example.com" {
allow-update { key "bindy-operator"; };
};"#;

let config = parse_showzone(input)?;

// Raw directive preserved
assert_eq!(config.allow_update_raw, Some("{ key \"bindy-operator\"; };".to_string()));
assert_eq!(config.allow_update, None);

// Serialization preserves key reference
let serialized = config.to_rndc_block();
assert!(serialized.contains("allow-update { key \"bindy-operator\"; }"));
```

**Key Features:**

- Key references preserved in `allow_update_raw` field
- PATCH operations preserve keys when modifying other fields
- Explicit IP setting clears raw directive
- No accidental modification of key-based permissions

## Limitations

### Not Currently Supported
### Not Currently Supported (Structured Parsing)

- **ACL Names**: `allow-transfer { "trusted"; };`
- **Complex ACLs**: `{ !10.0.0.1; any; };`
- **Key Definitions**: Only key references are handled
- **Custom Options**: Zone options beyond documented fields
While all options are preserved via `raw_options`, structured parsing is not yet implemented for:

- **ACL Names**: `allow-transfer { "trusted"; };` (preserved as raw)
- **Complex ACLs**: `{ !10.0.0.1; any; };` (preserved as raw)
- **Update Policy**: Complex grammar (preserved as raw string in `update_policy`)
- **Views**: View-specific zone configurations
- **Forwarders with TLS**: `forwarders { 10.1.1.1 tls tls-config; };` (structured type exists, parser pending)

**Note**: All these options are preserved and round-trip correctly through `raw_options` or dedicated raw fields (`allow_update_raw`, `update_policy`).

### Future Enhancements

See the [RNDC Parser Roadmap](../../roadmaps/rndc-conf-parser.md) for planned features:
See the [BIND9 Full Zone Config Support Roadmap](../../roadmaps/bind9-full-zone-config-support.md) for details:

- Structured parsers for common options (notify, forwarders, transfer timeouts)
- ACL name resolution
- View-aware zone configurations
- Parser for `rndc zonestatus` output
- Parser for `rndc status` output
- Parser for `rndc.conf` configuration files
- Support for ACL names and expressions
- View-aware zone configurations

## Implementation Details

Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ mod middleware_test;
mod rndc_test;
#[cfg(test)]
mod rndc_parser_tests;

#[cfg(test)]
mod rndc_types_tests;

#[cfg(test)]
mod types_test;
#[cfg(test)]
Expand Down
Loading
Loading