tenable 0.1.1

Tenable API abstraction for rust
Documentation
use crate::{Error, HttpRequest, Response, Tenable};
use http::{header::HeaderValue, status::StatusCode, Method, Request};
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, fmt};

/// Request Object for the `acr_update` function
#[derive(Clone, Debug)]
pub struct AcrUpdate<'a> {
    /// Inner tenable Client
    pub tenable: &'a Tenable<'a>,
    /// `Acr`s to send to tenable
    pub acrs: Cow<'a, [Acr]>,
}

impl<RE: fmt::Debug> HttpRequest<RE> for AcrUpdate<'_> {
    type Output = ();

    #[inline]
    fn to_request(&self) -> Result<Request<Vec<u8>>, Error<RE>> {
        let payload = serde_json::to_vec(&self.acrs)?;
        let req = Request::builder()
            .uri(format!("{}/api/v2/assets/bulk-jobs/acr", self.tenable.uri,))
            .method(Method::POST)
            .header(
                "X-ApiKeys",
                HeaderValue::from_str(self.tenable.auth.as_ref())?,
            )
            .header("Accept", HeaderValue::from_static("application/json"))
            .body(payload)?;
        Ok(req)
    }

    #[inline]
    fn from_response(&self, res: Response) -> Result<Self::Output, Error<RE>> {
        match res.status {
            StatusCode::OK => {}
            StatusCode::FORBIDDEN => return Err(Error::InsufficientPermission),
            StatusCode::TOO_MANY_REQUESTS => return Err(Error::RateLimitReached),
            code => return Err(Error::UnexpectedStatusCode(code)),
        }
        Ok(())
    }
}

impl<'a> From<AcrUpdate<'a>> for Cow<'a, AcrUpdate<'a>> {
    #[inline]
    fn from(req: AcrUpdate<'a>) -> Self {
        Cow::Owned(req)
    }
}

impl<'a> From<&'a AcrUpdate<'a>> for Cow<'a, AcrUpdate<'a>> {
    #[inline]
    fn from(req: &'a AcrUpdate<'a>) -> Self {
        Cow::Borrowed(req)
    }
}

#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
/// Parameters to update the ACR for an asset.
/// TODO: Cow
pub struct Acr {
    /// The ACR score you want to assign to the asset. The ACR must be an integer from 1 to 10.
    #[serde(rename = "acr_score")]
    pub acr_score: u64,
    /// The reasons you are updating the ACR for the assets. Supported values include:\n\n - Business Critical\n - In Scope For Compliance\n - Existing Mitigation Control\n - Dev only \n - Key drivers does not match \n - Other\n\nThis parameter corresponds to the **Overwrite Reasoning** parameter when editing an ACR in the Tenable.io Lumin user interface. For more information, see [Edit an ACR](https://docs.tenable.com/tenableio/vulnerabilitymanagement/Content/Analysis/LuminEditACR.htm).
    #[serde(rename = "reason", skip_serializing_if = "Option::is_none")]
    pub reason: Option<Vec<AcrUpdateReason>>,
    /// Any notes you want to add to clarify the circumstances behind the update. This parameter corresponds to the **Note** parameter when editing an ACR in the Tenable.io Lumin user interface. For more information, see [Edit an ACR](https://docs.tenable.com/tenableio/vulnerabilitymanagement/Content/Analysis/LuminEditACR.htm).
    #[serde(rename = "note", skip_serializing_if = "Option::is_none")]
    pub note: Option<String>,
    /// The identifiers of the assets to update to the specified ACR. At least one asset object is required in this array.
    #[serde(rename = "asset")]
    pub asset: Vec<AcrAsset>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Copy)]
#[allow(missing_docs)]
pub enum AcrUpdateReason {
    #[serde(rename = "Business Critical")]
    BusinessCritical,
    #[serde(rename = "In Scope For Compliance")]
    InScopeForCompliance,
    #[serde(rename = "Existing Mitigation Control")]
    ExistingMitigationControl,
    #[serde(rename = "Dev only")]
    DevOnly,
    #[serde(rename = "Key drivers does not match")]
    KeyDriversDoesNotMatch,
    #[serde(rename = "Other")]
    Other,
}

#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
/// Each object can contain a single instance of the properties described below. You can combine multiple instances of this object, each containing a different single property.
/// TODO: Cow
/// TODO: Switch to enum
pub struct AcrAsset {
    /// The UUID for a specific asset. Use this value as the unique key for the asset.
    #[serde(rename = "id", skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
    /// Fully-qualified domain names (FQDNs) associated with the asset or assets.
    #[serde(rename = "fqdn", skip_serializing_if = "Option::is_none")]
    pub fqdn: Option<Vec<String>>,
    /// MAC addresses associated with the asset or assets.
    #[serde(rename = "mac_address", skip_serializing_if = "Option::is_none")]
    pub mac_address: Option<String>,
    /// The NetBIOS name for the asset.
    #[serde(rename = "netbios_name", skip_serializing_if = "Option::is_none")]
    pub netbios_name: Option<String>,
    /// IPv4 addresses associated with the asset or assets.
    #[serde(rename = "ipv4", skip_serializing_if = "Option::is_none")]
    pub ipv4: Option<Vec<String>>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
/// `AccessGroupsRules` blueprint
pub struct AccessGroupsRules {
    /// The type of asset rule. The asset rule type corresponds to the type of data you can specify in the `terms` parameter. For a complete list of supported rule types, use the [GET /access-groups/filters](ref:io-v1-access-groups-list-filters) endpoint.
    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    pub _type: Option<String>,
    /// The operator that specifies how Tenable.io matches the terms value to asset data.   Possible operators include:   - eq—Tenable.io matches the rule to assets based on an exact match of the specified term. Note: Tenable.io interprets the operator as `equals` for ipv4 rules that specify a single IP address, but interprets the operator as `contains` for ipv4 rules that specify an IP range or CIDR range.  - match—Tenable.io matches the rule to assets based a partial match of the specified term.  - starts—Tenable.io matches the rule to assets that start with the specified term.  - ends—Tenable.io matches the rule to assets that end with the specified term.  For a complete list of operators by rule type, use the [GET /access-groups/rules/filters](ref:io-v1-access-groups-list-rule-filters) endpoint.
    #[serde(rename = "operator", skip_serializing_if = "Option::is_none")]
    pub operator: Option<String>,
    /// The values that Tenable.io uses to match an asset to the rule. A term must correspond to the rule type.  For example:  - If the rule type is `aws_account`, the term is an AWS account ID.  - If the rule type is `fqdn`, the term is a hostname or a fully-qualified domain name (FQDN).  - If the rule type is `ipv4`, the term is an individual IPv4 address, a range of IPv4 addresses (for example, 172.204.81.57-172.204.81.60), or a CIDR range (for example, 172.204.81.57/24).   For a complete list of supported values by rule type, use the [GET /access-groups/rules/filters](ref:io-v1-access-groups-list-rule-filters) endpoint.    If you specify multiple terms values, Tenable.io includes an asset in the access group if the asset's attributes match any of the terms in the rule. <br >You can specify up to 100,000 terms per asset rule.
    #[serde(rename = "terms", skip_serializing_if = "Option::is_none")]
    pub terms: Option<Vec<String>>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
/// `AccessGroupsPrincipals` blueprint
pub struct AccessGroupsPrincipals {
    /// (Required) The type of principal. Valid values include:  - user—Grants access to the user you specify.  - group—Grants access to all users assigned to the user group you specify.
    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    pub _type: Option<String>,
    /// The UUID of a user or user group. This parameter is required if the request omits the `principal_name` parameter.
    #[serde(rename = "principal_id", skip_serializing_if = "Option::is_none")]
    pub principal_id: Option<String>,
    /// The name of the user or user group. This parameter is required if the request omits the `principal_id` parameter. If a request includes both `principal_id` and `principal_name`, Tenable.io assigns the user or user group to the access group based on the `principal_id` parameter, and ignores the `principal_name` parameter in the request.
    #[serde(rename = "principal_name", skip_serializing_if = "Option::is_none")]
    pub principal_name: Option<String>,
}