-
Notifications
You must be signed in to change notification settings - Fork 0
Releases: fastrevmd-lab/rustnetconf
rustnetconf-yang v0.1.3 — docs clarification
Documentation-only patch release of the rustnetconf-yang crate (closes #30). No API or behavior changes. The rustnetconf library (0.12.0) and rustnetconf-cli (0.3.0) are unchanged.
Fixed
- Module docs now state that generated types require enabling the
generatedCargo feature (off by default) — without it theietf_*modules are absent. - Clarified that codegen reads the crate's own bundled
yang-models/, not the consumer's project; documented how to vendor the crate to use custom YANG files. - Corrected the usage example to the real generated API (
Option-wrapped fields, thetypeleaf is emitted astype_).
Assets 2
v0.12.0 — OpenSSH known_hosts host-key pinning
OpenSSH known_hosts-style host-key pinning for fleet operation. Closes #28.
Published to crates.io
rustnetconf0.12.0rustnetconf-cli0.3.0rustnetconf-yang0.1.2
New features
HostKeyVerification::KnownHosts(PathBuf)— verify the server's SHA-256 fingerprint against an OpenSSHknown_hosts(5)file on every connect. Supports plain hostnames,[host]:port, wildcards (*/?), CIDR networks, hashed|1|salt|hmac-sha1entries, and@revokedmarkers. Re-read on every connect — external rotation tools are picked up immediately.- New structured errors on
TransportError:HostKeyMismatch { host, expected, actual },HostKeyNotInKnownHosts { host, port, path },HostKeyRevoked { host }. - CLI: new optional
known_hosts_pathfield on[devices.*]and[defaults]ininventory.toml. Per-device value wins; setting bothhost_key_fingerprintandknown_hosts_pathon the same device is a hard error. examples/known_hosts.rsdemonstrates thessh-keyscan→KnownHosts(path)workflow.
Breaking changes
DeviceConfig(connection pool) gained a new fieldhost_key_verification: Option<HostKeyVerification>. Existing struct-literal callers must add the field.Nonemeans "use library default" (RejectAll).
Quality
- Live-device integration tests (
integration_vsrx,integration_vendor_pool) are now opt-in viaRUSTNETCONF_TEST_VSRX_HOST— without it the suite is a clean no-op for contributors without a Junos lab.
Merged via #29.
Assets 2
v0.11.0 — Security remediation pass
Security remediation pass — addresses the seven findings (RNC-SEC-001..006 + CI hardening) from the internal audit, merged via #27 and finalized in 8c29405.
Published on crates.io
| Crate | Version |
|---|---|
rustnetconf |
0.11.0 |
rustnetconf-cli |
0.2.0 |
rustnetconf-yang |
0.1.1 |
[dependencies] rustnetconf = "0.11" # optional: rustnetconf-yang = "0.1" # binary: cargo install rustnetconf-cli
Breaking changes
ClientBuilderdefaultHostKeyVerificationis nowRejectAll(fail closed). Connections refuse to complete until the caller pins a fingerprint or explicitly opts in toAcceptAll.ProxyJumphops parsed from~/.ssh/configlikewise default toRejectAll.inventory.toml: devicepasswordandkey_passphrasefields now deserialize into aSecretStringnewtype.DebugprintsSecretString(***)and contents zeroize on drop.ClientBuilder::password/.key_passphrasenow acceptOption<Zeroizing<String>>(was plainOption<String>).
Security fixes
- RNC-SEC-001 — SSH host-key verification fails closed by default in both the library and the CLI. New CLI flag
--insecure-accept-host-keyfor lab use; otherwisehost_key_fingerprintmust be set per device ininventory.toml. - RNC-SEC-002 — RUSTSEC-2023-0071 (
rsaMarvin Attack timing side-channel) risk-accepted via.cargo/audit.tomlwith reachability analysis and review date 2026年08月01日.russhbumped 0.60.2 → 0.60.3. - RNC-SEC-003 — Inventory passwords use the new
SecretStringtype with redactedDebugand a customDeserializethat zeroizes on drop. - RNC-SEC-004 — State files always land at
0o600via atomic temp-file +rename(2), even when a pre-existing file had looser permissions..netconfand.netconf/stateare forced to0o700on every call. Stale temp files from a prior crash are cleaned up. - RNC-SEC-005 —
applyandrollbackguarantee candidate-lock cleanup on error. NewClient::release_candidate_lock_best_effort(discard-changes + unlock, swallowing errors) is invoked from extracted*_locked_regionhelpers. - RNC-SEC-006 — Desired XML is validated for well-formedness before any device connection or candidate lock. Errors name the offending file.
CI hardening
- New
.github/workflows/ci.ymlruns build, test (workspace, all features),clippy -D warnings,rustfmt, andcargo auditon every push and PR tomain.
Quality fixes
- YANG codegen: generated
use super::*;/use crate::serialize::*;imports now carry#[allow(unused_imports)]so modules without leaf references compile cleanly under-D warnings. - YANG codegen test: corrected
r#type→type_to match the field-sanitization the generator actually emits.
Mitigation reminder
Use Ed25519 or ECDSA SSH keys (not RSA) to sidestep RUSTSEC-2023-0071. See README §Security for the full advisory write-up.
Full changelog: v0.10.0...v0.11.0
Assets 2
v0.9.0
rustnetconf v0.9.0 adds first-class SSH bastion support so you can reach managed devices that sit behind one or more jump hosts — without leaving the library.
Now on crates.io: https://crates.io/crates/rustnetconf/0.9.0
[dependencies] rustnetconf = "0.9"
Highlights
ProxyJump — multi-hop bastion chains (#15)
Tunnel NETCONF/SSH through one or more jump hosts. Each hop carries its own credentials and host-key policy (bastions usually have different access rules than the devices behind them).
use rustnetconf::transport::ssh::{JumpHostConfig, SshAuth, HostKeyVerification}; let bastion = JumpHostConfig { host: "bastion.example.com".into(), port: 22, username: "jumpuser".into(), auth: SshAuth::Agent, host_key_verification: HostKeyVerification::AcceptAll, }; let mut client = Client::connect("10.0.0.1:830") .username("admin") .ssh_agent() .jump_hosts(vec![bastion]) .connect() .await?;
ProxyCommand — arbitrary proxy programs (#16)
OpenSSH-style ProxyCommand: an arbitrary shell command whose stdin/stdout become the SSH transport. %h and %p are substituted to the target host/port (matching man 5 ssh_config).
let mut client = Client::connect("10.0.0.1:830") .username("admin") .ssh_agent() .proxy_command("ssh -W %h:%p bastion") .connect() .await?;
⚠️ ProxyCommandruns undersh -cand%his substituted literally (matching OpenSSH). Treat the command string as untrusted-input-sensitive.
OpenSSH ~/.ssh/config alias resolution (#17, closes #14)
Resolve a Host alias from your existing OpenSSH config rather than repeating connection details:
let mut client = Client::connect_via_ssh_config("edge-r1")? .ssh_agent() .connect() .await?;
Supported directives: Host (with */? glob + ! negation), HostName, Port, User, IdentityFile (with ~ expansion), ProxyJump, ProxyCommand, Include (recursively flattened, depth-limited to 16). First-match-wins semantics across all matching Host blocks (matches OpenSSH).
Match blocks are parsed-and-skipped with a debug log (out of scope for v1).
Notes
jump_hostsandproxy_commandare mutually exclusive at connect time.- NETCONF default port
830is used when ssh_config doesn't pinPort. - Backwards compatible — direct connections behave identically; all new options are additive.
- Test coverage: 179 lib tests passing (36 new for ssh_config, 6 for ProxyCommand, 4 for ProxyJump). Live tests against a real bastion deferred to integration.
What's Changed
- feat(ssh): add ProxyJump (jump-host) support — Phase 1 of #14 (#15)
- feat(ssh): add ProxyCommand support — Phase 2 of #14 (#16)
- feat: OpenSSH config parser +
Client::connect_via_ssh_config— Phase 3 of #14 (#17, closes #14)
Full Changelog: v0.8.2...v0.9.0