use crate::{
AwsError, AwsHttpClient, Result, ops::securityhub::SecurityhubOps,
types::securityhub::DescribeHubResponse,
};
pub struct SecurityHubClient<'a> {
ops: SecurityhubOps<'a>,
}
impl<'a> SecurityHubClient<'a> {
pub(crate) fn new(client: &'a AwsHttpClient) -> Self {
Self {
ops: SecurityhubOps::new(client),
}
}
pub async fn describe_hub(&self) -> Result<DescribeHubResponse> {
self.ops.describe_hub("").await
}
pub async fn is_enabled(&self) -> Result<bool> {
match self.ops.describe_hub("").await {
Ok(_) => Ok(true),
Err(AwsError::NotFound { .. }) => Ok(false),
Err(AwsError::ServiceError { status: 403, .. }) => Ok(false),
Err(e) => Err(e),
}
}
}
#[cfg(test)]
mod tests {
use crate::AwsError;
use serde_json::json;
#[tokio::test]
async fn test_describe_hub_returns_hub_details() {
let mut mock = crate::MockClient::new();
mock.expect_get("/accounts")
.returning_json(json!({
"HubArn": "arn:aws:securityhub:us-east-1:123456789012:hub/default",
"SubscribedAt": "2024-01-15T10:00:00.000Z",
"AutoEnableControls": true,
"ControlFindingGenerator": "SECURITY_CONTROL"
}))
.times(1);
let client = crate::AwsHttpClient::from_mock(mock);
let sh = client.securityhub();
let hub = sh.describe_hub().await.unwrap();
assert_eq!(
hub.hub_arn.as_deref(),
Some("arn:aws:securityhub:us-east-1:123456789012:hub/default")
);
assert_eq!(hub.auto_enable_controls, Some(true));
assert_eq!(
hub.control_finding_generator.as_deref(),
Some("SECURITY_CONTROL")
);
}
#[tokio::test]
async fn test_is_enabled_true() {
let mut mock = crate::MockClient::new();
mock.expect_get("/accounts")
.returning_json(json!({
"HubArn": "arn:aws:securityhub:us-east-1:123456789012:hub/default",
"SubscribedAt": "2024-01-15T10:00:00.000Z"
}))
.times(1);
let client = crate::AwsHttpClient::from_mock(mock);
assert!(client.securityhub().is_enabled().await.unwrap());
}
#[tokio::test]
async fn test_is_enabled_false_when_not_found() {
let mut mock = crate::MockClient::new();
mock.expect_get("/accounts")
.returning_error(AwsError::NotFound {
resource: "Account is not subscribed to AWS Security Hub".into(),
})
.times(1);
let client = crate::AwsHttpClient::from_mock(mock);
assert!(!client.securityhub().is_enabled().await.unwrap());
}
#[tokio::test]
async fn test_is_enabled_false_when_invalid_access() {
let mut mock = crate::MockClient::new();
mock.expect_get("/accounts")
.returning_error(AwsError::ServiceError {
code: "HttpError403".into(),
message: "The AWS Access Key Id needs a subscription for the service".into(),
status: 403,
})
.times(1);
let client = crate::AwsHttpClient::from_mock(mock);
assert!(!client.securityhub().is_enabled().await.unwrap());
}
}