misp_client_rs/apis/
objects_api.rs

1//!
2//! MISP Automation API
3//!
4//!  ### Getting Started  MISP API allows you to query, create, modify data models, such as [Events](https://www.circl.lu/doc/misp/GLOSSARY.html#misp-event), [Objects](https://www.circl.lu/doc/misp/misp-objects/), [Attributes](https://www.circl.lu/doc/misp/GLOSSARY.html#misp-attribute). This is extremly useful for interconnecting MISP with external tools and feeding other systems with threat intel data.  It also lets you perform administrative tasks such as creating users, organisations, altering MISP settings, and much more.  To get an API key there are several options: * **[UI]** Go to [My Profile -> Auth Keys](/auth_keys/index) section and click on `+ Add authentication key`  * **[UI]** As an admin go to the the [Administration -> List Users -> View](/admin/users/view/[id]) page of the user you want to create an auth key for and on the `Auth keys` section click on `+ Add authentication key`  * **[CLI]** Use the following command: `./app/Console/cake user change_authkey [e-mail/user_id]`  * **API** Provided you already have an admin level API key, you can create an API key for another user using the `[POST]/auth_keys/add/{{user_id}}` endpoint.  > **NOTE:** The authentication key will only be displayed once, so take note of it or store it properly in your application secrets.  #### Accept and Content-Type headers  When performing your request, depending on the type of request, you might need to explicitly specify in what content  type you want to get your results. This is done by setting one of the below `Accept` headers:      Accept: application/json     Accept: application/xml  When submitting data in a `POST`, `PUT` or `DELETE` operation you also need to specify in what content-type you encoded the payload.  This is done by setting one of the below `Content-Type` headers:      Content-Type: application/json     Content-Type: application/xml  Example: ``` curl  --header \"Authorization: YOUR_API_KEY\" \\       --header \"Accept: application/json\" \\       --header \"Content-Type: application/json\" https://<misp url>/  ```  > **NOTE**: By appending .json or .xml the content type can also be set without the need for a header.  #### Automation using PyMISP  [PyMISP](https://github.com/MISP/PyMISP) is a Python library to access MISP platforms via their REST [API](https://www.circl.lu/doc/misp/GLOSSARY.html#api). It allows you to fetch events, add or update events/attributes, add or update samples or search for attributes.  ### FAQ * [Dev FAQ](https://www.circl.lu/doc/misp/dev-faq/) * [GitHub project FAQ](https://github.com/MISP/MISP/wiki/Frequently-Asked-Questions) 
5//!
6//! The version of the OpenAPI document: 2.4
7//! 
8//! Generated by: https://openapi-generator.tech
9//! 
10
11
12use reqwest;
13use serde::{Deserialize, Serialize, de::Error as _};
14use crate::{apis::ResponseContent, models};
15use super::{Error, configuration, ContentType};
16
17
18/// struct for typed errors of method [`add_object`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum AddObjectError {
22    Status403(models::UnauthorizedApiError),
23    Status404(models::NotFoundApiError),
24    DefaultResponse(models::ApiError),
25    UnknownValue(serde_json::Value),
26}
27
28/// struct for typed errors of method [`delete_object`]
29#[derive(Debug, Clone, Serialize, Deserialize)]
30#[serde(untagged)]
31pub enum DeleteObjectError {
32    Status403(models::UnauthorizedApiError),
33    Status404(models::NotFoundApiError),
34    DefaultResponse(models::ApiError),
35    UnknownValue(serde_json::Value),
36}
37
38/// struct for typed errors of method [`get_object_by_id`]
39#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(untagged)]
41pub enum GetObjectByIdError {
42    Status403(models::UnauthorizedApiError),
43    Status404(models::NotFoundApiError),
44    DefaultResponse(models::ApiError),
45    UnknownValue(serde_json::Value),
46}
47
48/// struct for typed errors of method [`rest_search_objects`]
49#[derive(Debug, Clone, Serialize, Deserialize)]
50#[serde(untagged)]
51pub enum RestSearchObjectsError {
52    Status403(models::UnauthorizedApiError),
53    DefaultResponse(models::ApiError),
54    UnknownValue(serde_json::Value),
55}
56
57
58pub async fn add_object(configuration: &configuration::Configuration, event_id: &str, object_template_id: &str, add_object_request: Option<models::AddObjectRequest>) -> Result<models::AddObject200Response, Error<AddObjectError>> {
59    // add a prefix to parameters to efficiently prevent name collisions
60    let p_event_id = event_id;
61    let p_object_template_id = object_template_id;
62    let p_add_object_request = add_object_request;
63
64    let uri_str = format!("{}/objects/add/{eventId}/{objectTemplateId}", configuration.base_path, eventId=p_event_id.to_string(), objectTemplateId=p_object_template_id.to_string());
65    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
66
67    if let Some(ref user_agent) = configuration.user_agent {
68        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
69    }
70    if let Some(ref apikey) = configuration.api_key {
71        let key = apikey.key.clone();
72        let value = match apikey.prefix {
73            Some(ref prefix) => format!("{} {}", prefix, key),
74            None => key,
75        };
76        req_builder = req_builder.header("Authorization", value);
77    };
78    req_builder = req_builder.json(&p_add_object_request);
79
80    let req = req_builder.build()?;
81    let resp = configuration.client.execute(req).await?;
82
83    let status = resp.status();
84    let content_type = resp
85        .headers()
86        .get("content-type")
87        .and_then(|v| v.to_str().ok())
88        .unwrap_or("application/octet-stream");
89    let content_type = super::ContentType::from(content_type);
90
91    if !status.is_client_error() && !status.is_server_error() {
92        let content = resp.text().await?;
93        match content_type {
94            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
95            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::AddObject200Response`"))),
96            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::AddObject200Response`")))),
97        }
98    } else {
99        let content = resp.text().await?;
100        let entity: Option<AddObjectError> = serde_json::from_str(&content).ok();
101        Err(Error::ResponseError(ResponseContent { status, content, entity }))
102    }
103}
104
105pub async fn delete_object(configuration: &configuration::Configuration, object_id: &str, hard_delete: &str) -> Result<models::DeleteObject200Response, Error<DeleteObjectError>> {
106    // add a prefix to parameters to efficiently prevent name collisions
107    let p_object_id = object_id;
108    let p_hard_delete = hard_delete;
109
110    let uri_str = format!("{}/objects/delete/{objectId}/{hardDelete}", configuration.base_path, objectId=p_object_id.to_string(), hardDelete=crate::apis::urlencode(p_hard_delete));
111    let mut req_builder = configuration.client.request(reqwest::Method::DELETE, &uri_str);
112
113    if let Some(ref user_agent) = configuration.user_agent {
114        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
115    }
116    if let Some(ref apikey) = configuration.api_key {
117        let key = apikey.key.clone();
118        let value = match apikey.prefix {
119            Some(ref prefix) => format!("{} {}", prefix, key),
120            None => key,
121        };
122        req_builder = req_builder.header("Authorization", value);
123    };
124
125    let req = req_builder.build()?;
126    let resp = configuration.client.execute(req).await?;
127
128    let status = resp.status();
129    let content_type = resp
130        .headers()
131        .get("content-type")
132        .and_then(|v| v.to_str().ok())
133        .unwrap_or("application/octet-stream");
134    let content_type = super::ContentType::from(content_type);
135
136    if !status.is_client_error() && !status.is_server_error() {
137        let content = resp.text().await?;
138        match content_type {
139            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
140            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::DeleteObject200Response`"))),
141            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::DeleteObject200Response`")))),
142        }
143    } else {
144        let content = resp.text().await?;
145        let entity: Option<DeleteObjectError> = serde_json::from_str(&content).ok();
146        Err(Error::ResponseError(ResponseContent { status, content, entity }))
147    }
148}
149
150pub async fn get_object_by_id(configuration: &configuration::Configuration, object_id: &str) -> Result<models::GetObjectById200Response, Error<GetObjectByIdError>> {
151    // add a prefix to parameters to efficiently prevent name collisions
152    let p_object_id = object_id;
153
154    let uri_str = format!("{}/objects/view/{objectId}", configuration.base_path, objectId=p_object_id.to_string());
155    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
156
157    if let Some(ref user_agent) = configuration.user_agent {
158        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
159    }
160    if let Some(ref apikey) = configuration.api_key {
161        let key = apikey.key.clone();
162        let value = match apikey.prefix {
163            Some(ref prefix) => format!("{} {}", prefix, key),
164            None => key,
165        };
166        req_builder = req_builder.header("Authorization", value);
167    };
168
169    let req = req_builder.build()?;
170    let resp = configuration.client.execute(req).await?;
171
172    let status = resp.status();
173    let content_type = resp
174        .headers()
175        .get("content-type")
176        .and_then(|v| v.to_str().ok())
177        .unwrap_or("application/octet-stream");
178    let content_type = super::ContentType::from(content_type);
179
180    if !status.is_client_error() && !status.is_server_error() {
181        let content = resp.text().await?;
182        match content_type {
183            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
184            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetObjectById200Response`"))),
185            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetObjectById200Response`")))),
186        }
187    } else {
188        let content = resp.text().await?;
189        let entity: Option<GetObjectByIdError> = serde_json::from_str(&content).ok();
190        Err(Error::ResponseError(ResponseContent { status, content, entity }))
191    }
192}
193
194/// **This is the recommended endpoint for searching objects.** 
195pub async fn rest_search_objects(configuration: &configuration::Configuration, object_rest_search_filter: models::ObjectRestSearchFilter) -> Result<models::RestSearchObjects200Response, Error<RestSearchObjectsError>> {
196    // add a prefix to parameters to efficiently prevent name collisions
197    let p_object_rest_search_filter = object_rest_search_filter;
198
199    let uri_str = format!("{}/objects/restsearch", configuration.base_path);
200    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
201
202    if let Some(ref user_agent) = configuration.user_agent {
203        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
204    }
205    if let Some(ref apikey) = configuration.api_key {
206        let key = apikey.key.clone();
207        let value = match apikey.prefix {
208            Some(ref prefix) => format!("{} {}", prefix, key),
209            None => key,
210        };
211        req_builder = req_builder.header("Authorization", value);
212    };
213    req_builder = req_builder.json(&p_object_rest_search_filter);
214
215    let req = req_builder.build()?;
216    let resp = configuration.client.execute(req).await?;
217
218    let status = resp.status();
219    let content_type = resp
220        .headers()
221        .get("content-type")
222        .and_then(|v| v.to_str().ok())
223        .unwrap_or("application/octet-stream");
224    let content_type = super::ContentType::from(content_type);
225
226    if !status.is_client_error() && !status.is_server_error() {
227        let content = resp.text().await?;
228        match content_type {
229            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
230            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::RestSearchObjects200Response`"))),
231            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::RestSearchObjects200Response`")))),
232        }
233    } else {
234        let content = resp.text().await?;
235        let entity: Option<RestSearchObjectsError> = serde_json::from_str(&content).ok();
236        Err(Error::ResponseError(ResponseContent { status, content, entity }))
237    }
238}
239