firewall-objects 0.1.3

Firewall object primitives for networks, services, and application indicators.
Documentation
# firewall-objects

[![Crates.io](https://img.shields.io/crates/v/firewall-objects.svg)](https://crates.io/crates/firewall-objects)
[![Docs.rs](https://docs.rs/firewall-objects/badge.svg)](https://docs.rs/firewall-objects)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

`firewall-objects` is a lightweight Rust framework for describing firewall entities—networks, transport services, and application indicators—so you can plug the building blocks into any policy engine, API, or control plane.

## Highlights

- **Network primitives** – Parse hosts, CIDR ranges, IP spans, and FQDNs with deterministic ordering and doc-tested examples.
- **Service catalog** – Represent TCP/UDP/ICMP/IP entries, extend well-known aliases, and go from strings to strongly typed objects.
- **Application descriptors** – Express Layer-7 indicators (DNS suffixes, TLS SNI, HTTP hosts) with matching helpers and a sample catalog.
- **Object store** – Optional in-memory registry with JSON import/export (via the `serde` feature) for CRUD-style workflows.

## Installation

```toml
[dependencies]
firewall-objects = "0.1.3"
# Optional JSON support
firewall-objects = { version = "0.1.1", features = ["serde"] }
```

### Features

- `serde` *(optional)* – Enables serialization for all public structs/enums and activates JSON helpers in the `objects` module.

## Networks: parsing and normalization

Use the `ip` module to normalize user input. Each call produces a deterministic `Network` variant.

```rust
use firewall_objects::ip::network::Network;
use std::str::FromStr;

let host = Network::from_str("192.0.2.10").unwrap();
let cidr = Network::from_str("2001:db8::/48").unwrap();
assert!(host < cidr); // ordering is stable
```

## Services: transport definitions and aliases

`TransportService` represents TCP, UDP, ICMP, and IP protocol entries. Lookup helpers cover common aliases.

```rust
use firewall_objects::service::{registry, TransportService};
use std::str::FromStr;

let https = registry::lookup("https").unwrap();
assert_eq!(https.to_string(), "tcp/443");

let custom = TransportService::from_str("udp/6000").unwrap();
assert_eq!(custom, TransportService::udp(6000));
```

## Applications: indicators and catalog lookups

Describe application behavior by combining DNS, TLS, and HTTP hints. The sample catalog is optional—bring your own definitions if you prefer.

```rust
use firewall_objects::service::{
    find_application,
    ApplicationMatchInput,
};

let github = find_application("github").unwrap();
let metadata = ApplicationMatchInput {
    dns_query: Some("status.github.com"),
    ..Default::default()
};
assert!(github.matches(&metadata));
```

## Object store: managing firewall objects

The `objects` module provides a small storage layer with create/read/update/delete helpers. Everything is strongly typed; JSON I/O is available when the `serde` feature is enabled. Helper methods keep the API approachable.

```rust
use firewall_objects::objects::ObjectStore;
use firewall_objects::ip::network::NetworkObj;

let mut store = ObjectStore::new();
store
    .insert_network(NetworkObj::try_from(("app1", "192.0.2.10")).unwrap())
    .unwrap();

let network = store.network("app1").unwrap();
println!("{network:?}");
```

To serialize/deserialize via JSON (requires the `serde` feature):

```rust
# use firewall_objects::objects::{ObjectStore, ObjectKind};
# use firewall_objects::service::{ServiceObj, TransportService};
# #[cfg(feature = "serde")]
let mut store = ObjectStore::new();
# #[cfg(feature = "serde")]
{
    store.insert_service(ServiceObj::new("dns".into(), TransportService::udp(53))).unwrap();
    let json = store.to_json(ObjectKind::Service, "dns").unwrap();
    assert!(json.contains("\"dns\""));
}
```

Applications can be stored and matched as well:

```rust
use firewall_objects::objects::ObjectStore;
use firewall_objects::service::{
    ApplicationDefinition,
    ApplicationIndicators,
    ApplicationMatchInput,
    ApplicationObj,
    TransportService,
};

let mut store = ObjectStore::new();

let app = ApplicationObj {
    name: "metrics-ui".into(),
    category: "internal".into(),
    transports: vec![TransportService::tcp(443)],
    dns_suffixes: vec![".corp.local".into()],
    tls_sni_suffixes: vec![],
    http_hosts: vec!["metrics.corp.local".into()],
};
store.insert_application(app.clone()).unwrap();

let stored = store.application("metrics-ui").unwrap();
assert!(stored.matches(&ApplicationMatchInput {
    http_host: Some("metrics.corp.local"),
    ..Default::default()
}));

// Extend the catalog with your own definitions
pub const MY_APPS: &[ApplicationDefinition<'static>] = &[
    ApplicationDefinition {
        name: "internal-dashboard",
        category: "internal",
        transports: &[TransportService::tcp(8443)],
        indicators: ApplicationIndicators {
            dns_suffixes: &[".internal.corp"],
            tls_sni_suffixes: &[".internal.corp"],
            http_hosts: &["dashboard.internal.corp"],
        },
    },
];
```

## Builder mode: rapid prototyping with dotted notation

For quick scripts or CLI playgrounds, the `builder` module offers ergonomic helpers that turn dotted notation into fully typed objects. Use `address(name, value)` for networks, `builder::service::*` helpers for transports, fluent `service_group()`/`network_group()` builders, and `builder::application()` for Layer-7 entries.

```rust
use firewall_objects::builder::{address, application, service, service_group};
use firewall_objects::objects::ObjectStore;

let mut store = ObjectStore::new();

for entry in [
    address("server1", "192.168.50.10").unwrap(),
    address("Public DMZ", "10.10.105.0/24").unwrap(),
    address("GMAIL", "www.gmail.com").unwrap(),
    address("jboss pool", "10.10.100.10-10.10.100.20").unwrap(),
] {
    store.add(entry).unwrap();
}

let allowed = service_group("allowed-services")
    .unwrap()
    .with_service(service::tcp(12849))
    .unwrap()
    .with_service(service::udp(1161))
    .unwrap()
    .with_service(service::parse("icmp/echo-request").unwrap())
    .unwrap()
    .build()
    .unwrap();
store.add(allowed).unwrap();

let zoom = application("zoom-collab", "collaboration")
    .unwrap()
    .transport("tcp/443").unwrap()
    .transport("udp/3478").unwrap()
    .dns_suffix(".zoom.us")
    .tls_sni_suffix(".zoom.us")
    .http_host("zoom.us")
    .build();
store.add(zoom).unwrap();
```

## Module Overview

- `ip` – Network entities and parsing utilities.
- `service` – Transport services, registries, and application descriptors.
- `objects` – Optional storage helpers with CRUD-style operations.
- `error` – Shared error type and result alias.

## License

MIT. Contributions and feedback are always welcome!