bindcar/
lib.rs

1// Copyright (c) 2025 Erick Bourgeois, firestoned
2// SPDX-License-Identifier: MIT
3
4//! bindcar - HTTP REST API for managing BIND9 zones via RNDC
5//!
6//! A lightweight library that provides programmatic control over BIND9 DNS zones
7//! using the RNDC (Remote Name Daemon Control) protocol.
8//!
9//! # Features
10//!
11//! - Create, delete, and manage BIND9 zones dynamically
12//! - Execute RNDC commands asynchronously
13//! - Zone file generation and management
14//! - Shared request/response types for API operations
15//! - Authentication support (Bearer tokens and Kubernetes ServiceAccounts)
16//! - Prometheus metrics integration
17//!
18//! # Usage
19//!
20//! This crate can be used as both a library and a standalone binary:
21//!
22//! ## As a Library
23//!
24//! ### Using RNDC Executor
25//!
26//! ```rust,no_run
27//! use bindcar::RndcExecutor;
28//!
29//! #[tokio::main]
30//! async fn main() -> anyhow::Result<()> {
31//!     let executor = RndcExecutor::new(
32//!         "127.0.0.1:953".to_string(),
33//!         "sha256".to_string(),
34//!         "dGVzdC1zZWNyZXQtaGVyZQ==".to_string(), // base64 encoded secret
35//!     )?;
36//!
37//!     // Execute RNDC commands
38//!     let status = executor.status().await?;
39//!     println!("BIND9 Status: {}", status);
40//!
41//!     Ok(())
42//! }
43//! ```
44//!
45//! ### Using Shared Types (for API clients)
46//!
47//! ```rust
48//! use bindcar::{CreateZoneRequest, ZoneConfig, SoaRecord, DnsRecord};
49//! use std::collections::HashMap;
50//!
51//! // Create nameserver glue records
52//! let mut ns_ips = HashMap::new();
53//! ns_ips.insert("ns1.example.com.".to_string(), "192.0.2.10".to_string());
54//!
55//! // Create a zone creation request
56//! let request = CreateZoneRequest {
57//!     zone_name: "example.com".to_string(),
58//!     zone_type: "primary".to_string(),
59//!     zone_config: ZoneConfig {
60//!         ttl: 3600,
61//!         soa: SoaRecord {
62//!             primary_ns: "ns1.example.com.".to_string(),
63//!             admin_email: "admin.example.com.".to_string(),
64//!             serial: 2025010101,
65//!             refresh: 3600,
66//!             retry: 600,
67//!             expire: 604800,
68//!             negative_ttl: 86400,
69//!         },
70//!         name_servers: vec!["ns1.example.com.".to_string()],
71//!         name_server_ips: ns_ips,
72//!         records: vec![
73//!             DnsRecord {
74//!                 name: "@".to_string(),
75//!                 record_type: "A".to_string(),
76//!                 value: "192.0.2.1".to_string(),
77//!                 ttl: None,
78//!                 priority: None,
79//!             },
80//!         ],
81//!         also_notify: None,
82//!         allow_transfer: None,
83//!         primaries: None,
84//!         dnssec_policy: None,
85//!         inline_signing: None,
86//!     },
87//!     update_key_name: None,
88//! };
89//!
90//! // Serialize to JSON for API requests
91//! let json = serde_json::to_string(&request).unwrap();
92//! ```
93//!
94//! ## As a Binary
95//!
96//! ```bash
97//! cargo install bindcar
98//! bindcar
99//! ```
100//!
101//! ## Zone File Generation
102//!
103//! The `serial` field in SoaRecord will auto-generate in YYYYMMDD01 format if omitted from JSON.
104//!
105//! ```rust
106//! use bindcar::{ZoneConfig, SoaRecord, DnsRecord};
107//! use std::collections::HashMap;
108//!
109//! // Example JSON can omit serial for auto-generation:
110//! let json = r#"{
111//!   "ttl": 3600,
112//!   "soa": {
113//!     "primaryNs": "ns1.example.com.",
114//!     "adminEmail": "admin.example.com."
115//!   },
116//!   "nameServers": ["ns1.example.com."],
117//!   "nameServerIps": {
118//!     "ns1.example.com.": "192.0.2.10"
119//!   },
120//!   "records": []
121//! }"#;
122//!
123//! let zone_config: ZoneConfig = serde_json::from_str(json).unwrap();
124//! let zone_file_content = zone_config.to_zone_file();
125//! println!("{}", zone_file_content);
126//! ```
127//!
128//! # Integration with Other Projects
129//!
130//! This library is designed to be used by other projects (like bindy) that need to
131//! interact with the bindcar API. By importing this crate, you get:
132//!
133//! - Type-safe request/response structures
134//! - Automatic JSON serialization/deserialization
135//! - OpenAPI schema compatibility
136//! - No need to maintain duplicate type definitions
137
138// Re-export public modules
139pub mod auth;
140pub mod metrics;
141pub mod middleware;
142pub mod nsupdate;
143pub mod rate_limit;
144pub mod records;
145pub mod rndc;
146pub mod rndc_conf_parser;
147pub mod rndc_conf_types;
148pub mod rndc_parser;
149pub mod rndc_types;
150pub mod types;
151pub mod zones;
152
153// Re-export commonly used types
154
155// RNDC executor
156pub use rndc::RndcExecutor;
157
158// nsupdate executor
159pub use nsupdate::NsupdateExecutor;
160
161// Error types
162pub use types::{ApiError, AppState, ErrorResponse};
163
164// Zone configuration types
165pub use zones::{DnsRecord, SoaRecord, ZoneConfig};
166
167// Request/Response types for API operations
168pub use zones::{
169    CreateZoneRequest, ServerStatusResponse, ZoneInfo, ZoneListResponse, ZoneResponse,
170    ZONE_TYPE_PRIMARY, ZONE_TYPE_SECONDARY,
171};
172
173// Record management types
174pub use records::{AddRecordRequest, RecordResponse, RemoveRecordRequest, UpdateRecordRequest};
175
176// RNDC configuration
177pub use rndc::{parse_rndc_conf, RndcConfig};
178
179// RNDC configuration parser
180pub use rndc_conf_parser::{parse_rndc_conf_file, parse_rndc_conf_str};
181
182// RNDC configuration types
183pub use rndc_conf_types::{KeyBlock, OptionsBlock, RndcConfFile, ServerAddress, ServerBlock};
184
185// Test modules
186#[cfg(test)]
187mod auth_test;
188#[cfg(test)]
189mod metrics_test;
190#[cfg(test)]
191mod middleware_test;
192#[cfg(test)]
193mod nsupdate_test;
194#[cfg(test)]
195mod rate_limit_test;
196#[cfg(test)]
197mod records_test;
198#[cfg(test)]
199mod rndc_parser_tests;
200#[cfg(test)]
201mod rndc_test;
202#[cfg(test)]
203mod rndc_types_tests;
204#[cfg(test)]
205mod types_test;
206#[cfg(test)]
207mod zones_test;