SassafrasAI/intel471-rs

GitHub: SassafrasAI/intel471-rs

Stars: 0 | Forks: 0

# intel471-rs An async Rust client library for the [Intel471](https://intel471.com) cyber threat intelligence platform. ## Overview `intel471-rs` provides typed, ergonomic access to the Intel471 API. It covers all 13 API services with streaming pagination, single-resource lookups, monitor CRUD, and raw response handling where appropriate. The library uses HTTP Basic Auth with your Verity API application credentials (client ID and client secret) and supports configurable base URLs for testing environments. ## Installation Add the crate to your `Cargo.toml`: [dependencies] intel471-rs = "0.1" Or via `cargo add`: cargo add intel471-rs ## Authentication The Intel471 API authenticates via HTTP Basic Auth using your Verity application credentials. Create an application in the Verity Developer Portal to obtain a client ID and client secret, then pass them as the username and password respectively: use intel471_rs::Intel471Client; let client = Intel471Client::new("client_id", "client_secret"); To use a custom base URL: let client = Intel471Client::with_base_url("client_id", "client_secret", "https://custom.api.example.com"); ## Quick Start use intel471_rs::Intel471Client; use intel471_rs::models::actors::ActorStreamRequest; #[tokio::main] async fn main() -> Result<(), Box> { let client = Intel471Client::new("client_id", "client_secret"); // Stream actors matching a search term let mut stream = client.actors().stream(ActorStreamRequest { actor: "Conti".to_string(), from: None, until: None, forum: None, server_type: None, size: Some(10), cursor: None, })?; while let Some(page) = stream.next_page().await? { for actor in &page.actors { println!("{}: {}", actor.id, actor.activity.first_seen_ts); } } Ok(()) } ## API Coverage | Service | Client Accessor | Key Methods | |---------|----------------|-------------| | Actors | `client.actors()` | `stream`, `stream_page` | | ASE | `client.ase()` | `list_monitors` | | Brand Exposure | `client.brand_exposure()` | Monitor CRUD, scan data endpoints, config endpoints | | Credentials | `client.credentials()` | Credential/set/occurrence streams and lookups | | Entities | `client.entities()` | `stream`, `stream_page` | | GIRS | `client.girs()` | `tree` | | Indicators | `client.indicators()` | `stream`, `stream_page`, `get_by_id` | | Malware Intel | `client.malware()` | `stream`, `get_by_id`, `list_malware`, `get_malware_family`, `download_file` | | Observables | `client.observables()` | `stream`, `stream_page` | | Reports | `client.reports()` | Stream/detail for FINTel, Breach Alert, Geopol, Info, Spot, Malware, Vulnerability reports | | Sources | `client.sources()` | Stream/detail for data-leak-site posts, forum posts/messages, chat messages | | TPRM | `client.tprm()` | Monitor CRUD, scan data endpoints, config endpoints | | Watchers | `client.watchers()` | `alerts_stream`, `update_alert_status`, `watcher_groups`, `watchers` | ## Usage ### Streaming with Pagination Many Intel471 endpoints return paginated results via a cursor-based API. The library exposes two patterns: - **`stream()`** returns a `PaginatedStream` for automatic cursor-based pagination. - **`stream_page()`** fetches a single page and returns the response directly. use intel471_rs::Intel471Client; use intel471_rs::models::actors::ActorStreamPage; use intel471_rs::api::actors::ActorStreamRequest; let client = Intel471Client::new("client_id", "client_secret"); // Automatic pagination let mut stream = client.actors().stream(ActorStreamRequest { actor: "Conti".to_string(), from: Some(1700000000), until: None, forum: None, server_type: None, size: Some(10), cursor: None, })?; while let Some(page) = stream.next_page().await? { println!("Page with {} actors", page.actors.len()); } // Collect all pages let all_pages: Vec = client .actors() .stream(ActorStreamRequest { actor: "Conti".to_string(), from: None, until: None, forum: None, server_type: None, size: None, cursor: None, })? .collect_all() .await?; ### Single-Resource Lookups // Get a credential by ID let credential = client.credentials().get_credential("credential-id").await?; // Get an indicator by ID let indicator = client.indicators().get_by_id("indicator-id").await?; // Get a malware event by ID let event = client.malware().get_by_id("event-id").await?; // Get the GIRS tree let tree = client.girs().tree().await?; for gir in &tree.girs { println!("{}: {}", gir.id.as_deref().unwrap_or("-"), gir.name.as_deref().unwrap_or("-")); } ### Monitor Management use intel471_rs::models::brand_exposure::{ CreateMonitorRequest, EditMonitorRequest, Frequency, Impact, ListMonitorsRequest, }; // Create a monitor let request = CreateMonitorRequest { name: "example.com".to_string(), targets: vec!["example.com".to_string()], labels: vec!["brand-monitor".to_string()], frequency: Frequency::daily, impact: Impact::major, alerts: None, created_at: None, disabled_modules: None, event_types: None, iteration: None, start_at: None, }; let response = client.brand_exposure().create_monitor(&request).await?; // List monitors let monitors = client.brand_exposure().list_monitors(ListMonitorsRequest { last_run_after: None, last_run_before: None, }).await?; // Edit a monitor client.brand_exposure().edit_monitor(&response.id, &EditMonitorRequest { name: "updated-name".to_string(), targets: vec!["example.com".to_string()], labels: vec!["brand-monitor".to_string()], frequency: Frequency::daily, impact: Impact::major, alerts: None, created_at: None, disabled_modules: None, event_types: None, iteration: None, start_at: None, }).await?; // Delete a monitor client.brand_exposure().delete_monitor(&response.id).await?; ### Error Handling The library provides a structured error type with convenience methods: use intel471_rs::Error; match client.credentials().get_credential("invalid-id").await { Ok(cred) => println!("{:?}", cred), Err(Error::Api { status: 404, .. }) => println!("Not found"), Err(Error::Api { status: 401, .. }) => println!("Unauthorized"), Err(Error::Api { status: 403, .. }) => println!("Forbidden"), Err(Error::Api { status: 429, .. }) => println!("Rate limited"), Err(e) => println!("Other error: {}", e), } // Convenience methods if let Err(e) = result { if e.is_not_found() { /* handle 404 */ } if e.is_unauthorized() { /* handle 401 */ } if e.is_forbidden() { /* handle 403 */ } if e.is_rate_limited() { /* handle 429/503 */ } } ## Crate Features The library is built on top of: ## Minimum Supported Rust Version This crate requires Rust 2024 edition (MSRV 1.85+). ## License Licensed under the [BSD 3-Clause License](LICENSE).
标签:通知系统