Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(aws): add new service firehose #5620

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
4 changes: 4 additions & 0 deletions prowler/providers/aws/services/firehose/firehose_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from prowler.providers.aws.services.firehose.firehose_service import Firehose
from prowler.providers.common.provider import Provider

firehose_client = Firehose(Provider.get_global_provider())
61 changes: 61 additions & 0 deletions prowler/providers/aws/services/firehose/firehose_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from typing import Dict, List, Optional

from botocore.client import ClientError
from pydantic import BaseModel, Field

from prowler.lib.logger import logger
from prowler.lib.scan_filters.scan_filters import is_resource_filtered
from prowler.providers.aws.lib.service.service import AWSService


class Firehose(AWSService):
def __init__(self, provider):
# Call AWSService's __init__
super().__init__(__class__.__name__, provider)
self.delivery_streams = {}
self.tags = []
MrCloudSec marked this conversation as resolved.
Show resolved Hide resolved
self.__threading_call__(self._list_delivery_streams)
self.__threading_call__(
self._list_tags_for_delivery_stream, self.delivery_streams.values()
)

def _list_delivery_streams(self, regional_client):
logger.info("Firehose - Listing delivery streams...")
try:
for stream in regional_client.list_delivery_streams()[
"DeliveryStreamNames"
]:
if not self.audit_resources or (
is_resource_filtered(stream, self.audit_resources)
):
stream_region = regional_client.region
stream_arn = f"arn:{self.audited_partition}:firehose:{stream_region}:{self.audited_account}:deliverystream/{stream}"
self.delivery_streams[stream_arn] = DeliveryStream(
arn=stream_arn,
name=stream,
region=stream_region,
)
except ClientError as error:
logger.error(

Check warning on line 39 in prowler/providers/aws/services/firehose/firehose_service.py

View check run for this annotation

Codecov / codecov/patch

prowler/providers/aws/services/firehose/firehose_service.py#L38-L39

Added lines #L38 - L39 were not covered by tests
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)

def _list_tags_for_delivery_stream(self, stream):
try:
stream.tags = (
self.regional_clients[stream.region]
.list_tags_for_delivery_stream(DeliveryStreamName=stream.name)
.get("Tags", [])
)
print(stream.tags)
MrCloudSec marked this conversation as resolved.
Show resolved Hide resolved
except ClientError as error:
logger.error(

Check warning on line 52 in prowler/providers/aws/services/firehose/firehose_service.py

View check run for this annotation

Codecov / codecov/patch

prowler/providers/aws/services/firehose/firehose_service.py#L51-L52

Added lines #L51 - L52 were not covered by tests
f"{stream.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)


class DeliveryStream(BaseModel):
arn: str
name: str
region: str
tags: Optional[List[Dict[str, str]]] = Field(default_factory=list)
2 changes: 1 addition & 1 deletion prowler/providers/aws/services/mq/mq_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class MQ(AWSService):
def __init__(self, provider):
# Call AWSService's __init__
super().__init__("mq", provider)
super().__init__(__class__.__name__, provider)
self.brokers = {}
self.__threading_call__(self._list_brokers)
self.__threading_call__(self._describe_broker, self.brokers.values())
Expand Down
69 changes: 69 additions & 0 deletions tests/providers/aws/services/firehose/firehose_service_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from boto3 import client
from moto import mock_aws

from prowler.providers.aws.services.firehose.firehose_service import Firehose
from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider


class Test_Firehose_Service:
# Test Firehose Service
@mock_aws
def test_service(self):
# Firehose client for this test class
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
firehose = Firehose(aws_provider)
assert firehose.service == "firehose"

# Test Firehose Client
@mock_aws
def test_client(self):
# Firehose client for this test class
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
firehose = Firehose(aws_provider)
for regional_client in firehose.regional_clients.values():
assert regional_client.__class__.__name__ == "Firehose"

# Test Firehose Session
@mock_aws
def test__get_session__(self):
# Firehose client for this test class
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
firehose = Firehose(aws_provider)
assert firehose.session.__class__.__name__ == "Session"

# Test Firehose List Delivery Streams
@mock_aws
def test_list_delivery_streams(self):
# Generate S3 client
s3_client = client("s3", region_name=AWS_REGION_EU_WEST_1)
s3_client.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": AWS_REGION_EU_WEST_1},
)

# Generate Firehose client
firehose_client = client("firehose", region_name=AWS_REGION_EU_WEST_1)
delivery_stream = firehose_client.create_delivery_stream(
DeliveryStreamName="test-delivery-stream",
DeliveryStreamType="DirectPut",
S3DestinationConfiguration={
"RoleARN": "arn:aws:iam::012345678901:role/firehose-role",
"BucketARN": "arn:aws:s3:::test-bucket",
"Prefix": "",
"BufferingHints": {"IntervalInSeconds": 300, "SizeInMBs": 5},
"CompressionFormat": "UNCOMPRESSED",
},
Tags=[{"Key": "key", "Value": "value"}],
)
arn = delivery_stream["DeliveryStreamARN"]
delivery_stream_name = arn.split("/")[-1]

# Firehose Client for this test class
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
firehose = Firehose(aws_provider)

assert len(firehose.delivery_streams) == 1
assert firehose.delivery_streams[arn].arn == arn
assert firehose.delivery_streams[arn].name == delivery_stream_name
assert firehose.delivery_streams[arn].region == AWS_REGION_EU_WEST_1
assert firehose.delivery_streams[arn].tags == [{"Key": "key", "Value": "value"}]