mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
feat(AwsProvider): include new structure for AWS provider (#3252)
Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Co-authored-by: Sergio Garcia <sergargar1@gmail.com>
This commit is contained in:
+6
-3
@@ -39,7 +39,6 @@ from prowler.lib.outputs.json import close_json
|
||||
from prowler.lib.outputs.outputs import extract_findings_statistics
|
||||
from prowler.lib.outputs.slack import send_slack_message
|
||||
from prowler.lib.outputs.summary_table import display_summary_table
|
||||
from prowler.providers.aws.aws_provider import get_available_aws_service_regions
|
||||
from prowler.providers.aws.lib.s3.s3 import send_to_s3_bucket
|
||||
from prowler.providers.aws.lib.security_hub.security_hub import (
|
||||
batch_send_to_security_hub,
|
||||
@@ -52,7 +51,10 @@ from prowler.providers.common.audit_info import (
|
||||
set_provider_execution_parameters,
|
||||
)
|
||||
from prowler.providers.common.clean import clean_provider_local_output_directories
|
||||
from prowler.providers.common.common import set_global_provider_object
|
||||
from prowler.providers.common.common import (
|
||||
get_global_provider,
|
||||
set_global_provider_object,
|
||||
)
|
||||
from prowler.providers.common.mutelist import set_provider_mutelist
|
||||
from prowler.providers.common.outputs import set_provider_output_options
|
||||
from prowler.providers.common.quick_inventory import run_provider_quick_inventory
|
||||
@@ -263,9 +265,10 @@ def prowler():
|
||||
f"{Style.BRIGHT}\nSending findings to AWS Security Hub, please wait...{Style.RESET_ALL}"
|
||||
)
|
||||
# Verify where AWS Security Hub is enabled
|
||||
global_provider = get_global_provider()
|
||||
aws_security_enabled_regions = []
|
||||
security_hub_regions = (
|
||||
get_available_aws_service_regions("securityhub", audit_info)
|
||||
global_provider.get_available_aws_service_regions("securityhub")
|
||||
if not audit_info.audited_regions
|
||||
else audit_info.audited_regions
|
||||
)
|
||||
|
||||
@@ -22,6 +22,7 @@ from prowler.lib.logger import logger
|
||||
from prowler.lib.outputs.outputs import report
|
||||
from prowler.lib.utils.utils import open_file, parse_json_file
|
||||
from prowler.providers.aws.lib.mutelist.mutelist import mutelist_findings
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
from prowler.providers.common.models import Audit_Metadata
|
||||
from prowler.providers.common.outputs import Provider_Output_Options
|
||||
|
||||
@@ -425,8 +426,10 @@ def execute_checks(
|
||||
services_executed = set()
|
||||
checks_executed = set()
|
||||
|
||||
global_provider = get_global_provider()
|
||||
|
||||
# Initialize the Audit Metadata
|
||||
audit_info.audit_metadata = Audit_Metadata(
|
||||
global_provider.audit_metadata = Audit_Metadata(
|
||||
services_scanned=0,
|
||||
expected_checks=checks_to_execute,
|
||||
completed_checks=0,
|
||||
@@ -537,6 +540,7 @@ def execute(
|
||||
checks_executed: set,
|
||||
custom_checks_metadata: Any,
|
||||
):
|
||||
global_provider = get_global_provider()
|
||||
# Import check module
|
||||
check_module_path = (
|
||||
f"prowler.providers.{provider}.services.{service}.{check_name}.{check_name}"
|
||||
@@ -556,15 +560,15 @@ def execute(
|
||||
# Update Audit Status
|
||||
services_executed.add(service)
|
||||
checks_executed.add(check_name)
|
||||
audit_info.audit_metadata = update_audit_metadata(
|
||||
audit_info.audit_metadata, services_executed, checks_executed
|
||||
global_provider.audit_metadata = update_audit_metadata(
|
||||
global_provider.audit_metadata, services_executed, checks_executed
|
||||
)
|
||||
|
||||
# Mute List findings
|
||||
if audit_output_options.mutelist_file:
|
||||
check_findings = mutelist_findings(
|
||||
audit_output_options.mutelist_file,
|
||||
audit_info.audited_account,
|
||||
global_provider.audited_account,
|
||||
check_findings,
|
||||
)
|
||||
|
||||
|
||||
@@ -172,9 +172,6 @@ def display_compliance_table(
|
||||
and compliance.Provider == "AWS"
|
||||
and compliance.Version == "RD2022"
|
||||
):
|
||||
compliance_version = compliance.Version
|
||||
compliance_fm = compliance.Framework
|
||||
compliance_provider = compliance.Provider
|
||||
for requirement in compliance.Requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
marco_categoria = (
|
||||
@@ -222,13 +219,13 @@ def display_compliance_table(
|
||||
ens_compliance_table["Bajo"].append(
|
||||
f"{Fore.YELLOW}{marcos[marco]['Bajo']}{Style.RESET_ALL}"
|
||||
)
|
||||
if fail_count + pass_count < 0:
|
||||
if fail_count + pass_count < 1:
|
||||
print(
|
||||
f"\n {Style.BRIGHT}There are no resources for {Fore.YELLOW}{compliance_fm}_{compliance_version}_{compliance_provider}{Style.RESET_ALL}.\n"
|
||||
f"\nThere are no resources for {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}.\n"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"\nEstado de Cumplimiento de {Fore.YELLOW}{compliance_fm}_{compliance_version}_{compliance_provider}{Style.RESET_ALL}:"
|
||||
f"\nEstado de Cumplimiento de {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}:"
|
||||
)
|
||||
overview_table = [
|
||||
[
|
||||
@@ -239,7 +236,7 @@ def display_compliance_table(
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
if not compliance_overview:
|
||||
print(
|
||||
f"\nResultados de {Fore.YELLOW}{compliance_fm}_{compliance_version}_{compliance_provider}{Style.RESET_ALL}:"
|
||||
f"\nResultados de {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}:"
|
||||
)
|
||||
print(
|
||||
tabulate(
|
||||
@@ -251,7 +248,9 @@ def display_compliance_table(
|
||||
print(
|
||||
f"{Style.BRIGHT}* Solo aparece el Marco/Categoria que contiene resultados.{Style.RESET_ALL}"
|
||||
)
|
||||
print(f"\nResultados detallados de {compliance_fm} en:")
|
||||
print(
|
||||
f"\nResultados detallados de {compliance_framework.upper()} en:"
|
||||
)
|
||||
print(
|
||||
f" - CSV: {output_directory}/compliance/{output_filename}_{compliance_framework}.csv\n"
|
||||
)
|
||||
@@ -272,8 +271,6 @@ def display_compliance_table(
|
||||
compliance.Framework == "CIS"
|
||||
and compliance.Version in compliance_framework
|
||||
):
|
||||
compliance_version = compliance.Version
|
||||
compliance_fm = compliance.Framework
|
||||
for requirement in compliance.Requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
section = attribute.Section
|
||||
@@ -322,11 +319,11 @@ def display_compliance_table(
|
||||
)
|
||||
if fail_count + pass_count < 1:
|
||||
print(
|
||||
f"\n {Style.BRIGHT}There are no resources for {Fore.YELLOW}{compliance_fm}_{compliance_version}{Style.RESET_ALL}.\n"
|
||||
f"\nThere are no resources for {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}.\n"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_fm}_{compliance_version}{Style.RESET_ALL} Framework:"
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
overview_table = [
|
||||
[
|
||||
@@ -337,7 +334,7 @@ def display_compliance_table(
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
if not compliance_overview:
|
||||
print(
|
||||
f"\nFramework {Fore.YELLOW}{compliance_fm}_{compliance_version}{Style.RESET_ALL} Results:"
|
||||
f"\nFramework {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Results:"
|
||||
)
|
||||
print(
|
||||
tabulate(
|
||||
@@ -349,7 +346,9 @@ def display_compliance_table(
|
||||
print(
|
||||
f"{Style.BRIGHT}* Only sections containing results appear.{Style.RESET_ALL}"
|
||||
)
|
||||
print(f"\nDetailed results of {compliance_fm} are in:")
|
||||
print(
|
||||
f"\nDetailed results of {compliance_framework.upper()} are in:"
|
||||
)
|
||||
print(
|
||||
f" - CSV: {output_directory}/compliance/{output_filename}_{compliance_framework}.csv\n"
|
||||
)
|
||||
@@ -369,7 +368,6 @@ def display_compliance_table(
|
||||
"MITRE-ATTACK" in compliance.Framework
|
||||
and compliance.Version in compliance_framework
|
||||
):
|
||||
compliance_fm = compliance.Framework
|
||||
for requirement in compliance.Requirements:
|
||||
for tactic in requirement.Tactics:
|
||||
if tactic not in tactics:
|
||||
@@ -396,11 +394,11 @@ def display_compliance_table(
|
||||
)
|
||||
if fail_count + pass_count < 1:
|
||||
print(
|
||||
f"\n {Style.BRIGHT}There are no resources for {Fore.YELLOW}{compliance_fm}{Style.RESET_ALL}.\n"
|
||||
f"\nThere are no resources for {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}.\n"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_fm}{Style.RESET_ALL} Framework:"
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
overview_table = [
|
||||
[
|
||||
@@ -411,7 +409,7 @@ def display_compliance_table(
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
if not compliance_overview:
|
||||
print(
|
||||
f"\nFramework {Fore.YELLOW}{compliance_fm}{Style.RESET_ALL} Results:"
|
||||
f"\nFramework {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Results:"
|
||||
)
|
||||
print(
|
||||
tabulate(
|
||||
@@ -423,7 +421,9 @@ def display_compliance_table(
|
||||
print(
|
||||
f"{Style.BRIGHT}* Only sections containing results appear.{Style.RESET_ALL}"
|
||||
)
|
||||
print(f"\nDetailed results of {compliance_fm} are in:")
|
||||
print(
|
||||
f"\nDetailed results of {compliance_framework.upper()} are in:"
|
||||
)
|
||||
print(
|
||||
f" - CSV: {output_directory}/compliance/{output_filename}_{compliance_framework}.csv\n"
|
||||
)
|
||||
@@ -447,7 +447,7 @@ def display_compliance_table(
|
||||
pass_count += 1
|
||||
if fail_count + pass_count < 1:
|
||||
print(
|
||||
f"\n {Style.BRIGHT}There are no resources for {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}.\n"
|
||||
f"\nThere are no resources for {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}.\n"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
|
||||
@@ -10,7 +10,7 @@ from prowler.config.config import prowler_version, timestamp
|
||||
from prowler.lib.check.models import Remediation
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.utils.utils import outputs_unix_timestamp
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Organizations_Info
|
||||
from prowler.providers.aws.lib.audit_info.models import AWSOrganizationsInfo
|
||||
|
||||
|
||||
def get_check_compliance(finding, provider, output_options) -> dict:
|
||||
@@ -483,7 +483,7 @@ class Aws_Check_Output_JSON(Check_Output_JSON):
|
||||
|
||||
Profile: str = ""
|
||||
AccountId: str = ""
|
||||
OrganizationsInfo: Optional[AWS_Organizations_Info]
|
||||
OrganizationsInfo: Optional[AWSOrganizationsInfo]
|
||||
Region: str = ""
|
||||
ResourceId: str = ""
|
||||
ResourceArn: str = ""
|
||||
|
||||
@@ -11,7 +11,7 @@ from prowler.lib.check.check import list_modules, recover_checks_from_service
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.utils.utils import open_file, parse_json_file
|
||||
from prowler.providers.aws.config import AWS_STS_GLOBAL_ENDPOINT_REGION
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Assume_Role, AWS_Audit_Info
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info, AWSAssumeRole
|
||||
from prowler.providers.aws.lib.credentials.credentials import create_sts_session
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ class AWS_Provider:
|
||||
|
||||
def assume_role(
|
||||
session: session.Session,
|
||||
assumed_role_info: AWS_Assume_Role,
|
||||
assumed_role_info: AWSAssumeRole,
|
||||
sts_endpoint_region: str = None,
|
||||
) -> dict:
|
||||
try:
|
||||
|
||||
@@ -0,0 +1,621 @@
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from argparse import Namespace
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any, Optional
|
||||
|
||||
from boto3 import client, session
|
||||
from botocore.config import Config
|
||||
from botocore.credentials import RefreshableCredentials
|
||||
from botocore.session import get_session
|
||||
from colorama import Fore, Style
|
||||
|
||||
from prowler.config.config import aws_services_json_file
|
||||
from prowler.lib.check.check import list_modules, recover_checks_from_service
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.utils.utils import open_file, parse_json_file
|
||||
from prowler.providers.aws.config import (
|
||||
AWS_STS_GLOBAL_ENDPOINT_REGION,
|
||||
BOTO3_USER_AGENT_EXTRA,
|
||||
)
|
||||
from prowler.providers.aws.lib.arn.arn import parse_iam_credentials_arn
|
||||
from prowler.providers.aws.lib.credentials.credentials import (
|
||||
create_sts_session,
|
||||
validate_AWSCredentials,
|
||||
)
|
||||
from prowler.providers.aws.lib.organizations.organizations import (
|
||||
get_organizations_metadata,
|
||||
)
|
||||
from prowler.providers.common.provider import Provider
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSOrganizationsInfo:
|
||||
account_details_email: str
|
||||
account_details_name: str
|
||||
account_details_arn: str
|
||||
account_details_org: str
|
||||
account_details_tags: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSCredentials:
|
||||
aws_access_key_id: str
|
||||
aws_session_token: str
|
||||
aws_secret_access_key: str
|
||||
expiration: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSAssumeRole:
|
||||
role_arn: str
|
||||
session_duration: int
|
||||
external_id: str
|
||||
mfa_enabled: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSAssumeRoleConfiguration:
|
||||
assumed_role_info: AWSAssumeRole
|
||||
assumed_role_credentials: AWSCredentials
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSIdentityInfo:
|
||||
account: str
|
||||
account_arn: str
|
||||
user_id: str
|
||||
partition: str
|
||||
identity_arn: str
|
||||
profile: str
|
||||
profile_region: str
|
||||
audited_regions: list
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWSSession:
|
||||
session: session.Session
|
||||
session_config: Config
|
||||
original_session: None
|
||||
|
||||
|
||||
class AwsProvider(Provider):
|
||||
session: AWSSession = AWSSession(
|
||||
session=None, session_config=None, original_session=None
|
||||
)
|
||||
identity: AWSIdentityInfo = AWSIdentityInfo(
|
||||
account=None,
|
||||
account_arn=None,
|
||||
user_id=None,
|
||||
partition=None,
|
||||
identity_arn=None,
|
||||
profile=None,
|
||||
profile_region=None,
|
||||
audited_regions=[],
|
||||
)
|
||||
assumed_role: AWSAssumeRoleConfiguration = AWSAssumeRoleConfiguration(
|
||||
assumed_role_info=AWSAssumeRole(
|
||||
role_arn=None,
|
||||
session_duration=None,
|
||||
external_id=None,
|
||||
mfa_enabled=False,
|
||||
),
|
||||
assumed_role_credentials=AWSCredentials(
|
||||
aws_access_key_id=None,
|
||||
aws_session_token=None,
|
||||
aws_secret_access_key=None,
|
||||
expiration=None,
|
||||
),
|
||||
)
|
||||
organizations_metadata: AWSOrganizationsInfo = AWSOrganizationsInfo(
|
||||
account_details_email=None,
|
||||
account_details_name=None,
|
||||
account_details_arn=None,
|
||||
account_details_org=None,
|
||||
account_details_tags=None,
|
||||
)
|
||||
audit_resources: Optional[Any]
|
||||
audit_metadata: Optional[Any]
|
||||
audit_config: dict = {}
|
||||
mfa_enabled: bool = False
|
||||
ignore_unused_services: bool = False
|
||||
|
||||
def __init__(self, arguments: Namespace):
|
||||
logger.info("Setting AWS provider ...")
|
||||
# Parse input arguments
|
||||
# Assume Role Options
|
||||
input_role = getattr(arguments, "role", None)
|
||||
input_session_duration = getattr(arguments, "session_duration", None)
|
||||
input_external_id = getattr(arguments, "external_id", None)
|
||||
|
||||
# STS Endpoint Region
|
||||
sts_endpoint_region = getattr(arguments, "sts_endpoint_region", None)
|
||||
|
||||
# MFA Configuration (false by default)
|
||||
input_mfa = getattr(arguments, "mfa", None)
|
||||
|
||||
input_profile = getattr(arguments, "profile", None)
|
||||
input_regions = getattr(arguments, "region", None)
|
||||
organizations_role_arn = getattr(arguments, "organizations_role", None)
|
||||
|
||||
# Set the maximum retries for the standard retrier config
|
||||
aws_retries_max_attempts = getattr(arguments, "aws_retries_max_attempts", None)
|
||||
|
||||
# Set if unused services must be ignored
|
||||
ignore_unused_services = getattr(arguments, "ignore_unused_services", None)
|
||||
|
||||
# Set the maximum retries for the standard retrier config
|
||||
self.session.session_config = self.__set_session_config__(
|
||||
aws_retries_max_attempts
|
||||
)
|
||||
|
||||
# Set ignore unused services
|
||||
self.ignore_unused_services = ignore_unused_services
|
||||
|
||||
# Start populating AWS identity object
|
||||
self.identity.profile = input_profile
|
||||
self.identity.audited_regions = input_regions
|
||||
|
||||
# We need to create an original sessions using regular auth path (creds, profile, etc)
|
||||
logger.info("Generating original session ...")
|
||||
self.session.session = self.setup_session(input_mfa)
|
||||
|
||||
# After the session is created, validate it
|
||||
logger.info("Validating credentials ...")
|
||||
caller_identity = validate_AWSCredentials(
|
||||
self.session.session, input_regions, sts_endpoint_region
|
||||
)
|
||||
|
||||
logger.info("Credentials validated")
|
||||
logger.info(f"Original caller identity UserId: {caller_identity['UserId']}")
|
||||
logger.info(f"Original caller identity ARN: {caller_identity['Arn']}")
|
||||
# Set values of AWS identity object
|
||||
self.identity.account = caller_identity["Account"]
|
||||
self.identity.identity_arn = caller_identity["Arn"]
|
||||
self.identity.user_id = caller_identity["UserId"]
|
||||
self.identity.partition = parse_iam_credentials_arn(
|
||||
caller_identity["Arn"]
|
||||
).partition
|
||||
self.identity.account_arn = (
|
||||
f"arn:{self.identity.partition}:iam::{self.identity.account}:root"
|
||||
)
|
||||
|
||||
# save original session
|
||||
self.session.original_session = self.session.session
|
||||
# time for checking role assumption
|
||||
if input_role:
|
||||
# session will be the assumed one
|
||||
self.session.session = self.setup_assumed_session(
|
||||
input_role,
|
||||
input_external_id,
|
||||
input_mfa,
|
||||
input_session_duration,
|
||||
sts_endpoint_region,
|
||||
)
|
||||
logger.info("Audit session is the new session created assuming role")
|
||||
# check if organizations info is gonna be retrieved
|
||||
if organizations_role_arn:
|
||||
logger.info(
|
||||
f"Getting organizations metadata for account {organizations_role_arn}"
|
||||
)
|
||||
# session will be the assumed one with organizations permissions
|
||||
self.session.session = self.setup_assumed_session(
|
||||
organizations_role_arn,
|
||||
input_external_id,
|
||||
input_mfa,
|
||||
input_session_duration,
|
||||
sts_endpoint_region,
|
||||
)
|
||||
self.organizations_metadata = get_organizations_metadata(
|
||||
self.identity.account, self.assumed_role.assumed_role_credentials
|
||||
)
|
||||
logger.info("Organizations metadata retrieved")
|
||||
if self.session.session.region_name:
|
||||
self.identity.profile_region = self.session.session.region_name
|
||||
else:
|
||||
self.identity.profile_region = "us-east-1"
|
||||
|
||||
if not getattr(arguments, "only_logs", None):
|
||||
self.print_credentials()
|
||||
|
||||
# Parse Scan Tags
|
||||
if getattr(arguments, "resource_tags", None):
|
||||
input_resource_tags = arguments.resource_tags
|
||||
self.audit_resources = self.get_tagged_resources(input_resource_tags)
|
||||
|
||||
# Parse Input Resource ARNs
|
||||
self.audit_resources = getattr(arguments, "resource_arn", None)
|
||||
|
||||
def setup_session(self, input_mfa: bool):
|
||||
logger.info("Creating regular session ...")
|
||||
# Input MFA only if a role is not going to be assumed
|
||||
if input_mfa and not self.assumed_role.assumed_role_info.role_arn:
|
||||
mfa_ARN, mfa_TOTP = self.__input_role_mfa_token_and_code__()
|
||||
get_session_token_arguments = {
|
||||
"SerialNumber": mfa_ARN,
|
||||
"TokenCode": mfa_TOTP,
|
||||
}
|
||||
sts_client = client("sts")
|
||||
session_credentials = sts_client.get_session_token(
|
||||
**get_session_token_arguments
|
||||
)
|
||||
return session.Session(
|
||||
aws_access_key_id=session_credentials["Credentials"]["AccessKeyId"],
|
||||
aws_secret_access_key=session_credentials["Credentials"][
|
||||
"SecretAccessKey"
|
||||
],
|
||||
aws_session_token=session_credentials["Credentials"]["SessionToken"],
|
||||
profile_name=self.identity.profile,
|
||||
)
|
||||
else:
|
||||
return session.Session(
|
||||
profile_name=self.identity.profile,
|
||||
)
|
||||
|
||||
def setup_assumed_session(
|
||||
self,
|
||||
input_role: str,
|
||||
input_external_id: str,
|
||||
input_mfa: str,
|
||||
session_duration: int,
|
||||
sts_endpoint_region: str,
|
||||
):
|
||||
logger.info("Creating assumed session ...")
|
||||
# store information about the role is gonna be assumed
|
||||
self.assumed_role.assumed_role_info.role_arn = input_role
|
||||
self.assumed_role.assumed_role_info.session_duration = session_duration
|
||||
self.assumed_role.assumed_role_info.external_id = input_external_id
|
||||
self.assumed_role.assumed_role_info.mfa_enabled = input_mfa
|
||||
# Check if role arn is valid
|
||||
try:
|
||||
# this returns the arn already parsed into a dict to be used when it is needed to access its fields
|
||||
role_arn_parsed = parse_iam_credentials_arn(
|
||||
self.assumed_role.assumed_role_info.role_arn
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.critical(f"{error.__class__.__name__} -- {error}")
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
logger.info(f"Assuming role {self.assumed_role.assumed_role_info.role_arn}")
|
||||
# Assume the role
|
||||
assumed_role_response = self.__assume_role__(
|
||||
self.session.session,
|
||||
sts_endpoint_region,
|
||||
)
|
||||
logger.info("Role assumed")
|
||||
# Set the info needed to create a session with an assumed role
|
||||
self.assumed_role.assumed_role_credentials = AWSCredentials(
|
||||
aws_access_key_id=assumed_role_response["Credentials"]["AccessKeyId"],
|
||||
aws_session_token=assumed_role_response["Credentials"]["SessionToken"],
|
||||
aws_secret_access_key=assumed_role_response["Credentials"][
|
||||
"SecretAccessKey"
|
||||
],
|
||||
expiration=assumed_role_response["Credentials"]["Expiration"],
|
||||
)
|
||||
# Set identity parameters
|
||||
self.identity.account = role_arn_parsed.account_id
|
||||
self.identity.partition = role_arn_parsed.partition
|
||||
self.identity.account_arn = (
|
||||
f"arn:{self.identity.partition}:iam::{self.identity.account}:root"
|
||||
)
|
||||
# From botocore we can use RefreshableCredentials class, which has an attribute (refresh_using)
|
||||
# that needs to be a method without arguments that retrieves a new set of fresh credentials
|
||||
# asuming the role again. -> https://github.com/boto/botocore/blob/098cc255f81a25b852e1ecdeb7adebd94c7b1b73/botocore/credentials.py#L395
|
||||
assumed_refreshable_credentials = RefreshableCredentials(
|
||||
access_key=self.assumed_role.assumed_role_credentials.aws_access_key_id,
|
||||
secret_key=self.assumed_role.assumed_role_credentials.aws_secret_access_key,
|
||||
token=self.assumed_role.assumed_role_credentials.aws_session_token,
|
||||
expiry_time=self.assumed_role.assumed_role_credentials.expiration,
|
||||
refresh_using=self.refresh_credentials,
|
||||
method="sts-assume-role",
|
||||
)
|
||||
# Here we need the botocore session since it needs to use refreshable credentials
|
||||
assumed_botocore_session = get_session()
|
||||
assumed_botocore_session._credentials = assumed_refreshable_credentials
|
||||
assumed_botocore_session.set_config_variable(
|
||||
"region", self.identity.profile_region
|
||||
)
|
||||
return session.Session(
|
||||
profile_name=self.identity.profile,
|
||||
botocore_session=assumed_botocore_session,
|
||||
)
|
||||
|
||||
# Refresh credentials method using assume role
|
||||
# This method is called "adding ()" to the name, so it cannot accept arguments
|
||||
# https://github.com/boto/botocore/blob/098cc255f81a25b852e1ecdeb7adebd94c7b1b73/botocore/credentials.py#L570
|
||||
def refresh_credentials(self):
|
||||
logger.info("Refreshing assumed credentials...")
|
||||
|
||||
response = self.__assume_role__(self.aws_session, self.role_info)
|
||||
refreshed_credentials = dict(
|
||||
# Keys of the dict has to be the same as those that are being searched in the parent class
|
||||
# https://github.com/boto/botocore/blob/098cc255f81a25b852e1ecdeb7adebd94c7b1b73/botocore/credentials.py#L609
|
||||
access_key=response["Credentials"]["AccessKeyId"],
|
||||
secret_key=response["Credentials"]["SecretAccessKey"],
|
||||
token=response["Credentials"]["SessionToken"],
|
||||
expiry_time=response["Credentials"]["Expiration"].isoformat(),
|
||||
)
|
||||
logger.info("Refreshed Credentials:")
|
||||
logger.info(refreshed_credentials)
|
||||
return refreshed_credentials
|
||||
|
||||
def print_credentials(self):
|
||||
# Beautify audited regions, set "all" if there is no filter region
|
||||
regions = (
|
||||
", ".join(self.identity.audited_regions)
|
||||
if self.identity.audited_regions is not None
|
||||
else "all"
|
||||
)
|
||||
# Beautify audited profile, set "default" if there is no profile set
|
||||
profile = (
|
||||
self.identity.profile if self.identity.profile is not None else "default"
|
||||
)
|
||||
|
||||
report = f"""
|
||||
This report is being generated using credentials below:
|
||||
|
||||
AWS-CLI Profile: {Fore.YELLOW}[{profile}]{Style.RESET_ALL} AWS Filter Region: {Fore.YELLOW}[{regions}]{Style.RESET_ALL}
|
||||
AWS Account: {Fore.YELLOW}[{self.identity.account}]{Style.RESET_ALL} UserId: {Fore.YELLOW}[{self.identity.user_id}]{Style.RESET_ALL}
|
||||
Caller Identity ARN: {Fore.YELLOW}[{ self.identity.identity_arn}]{Style.RESET_ALL}
|
||||
"""
|
||||
# If -A is set, print Assumed Role ARN
|
||||
if self.assumed_role.assumed_role_info.role_arn is not None:
|
||||
report += f"""Assumed Role ARN: {Fore.YELLOW}[{self.assumed_role.assumed_role_info.role_arn}]{Style.RESET_ALL}
|
||||
"""
|
||||
print(report)
|
||||
|
||||
def generate_regional_clients(
|
||||
self, service: str, global_service: bool = False
|
||||
) -> dict:
|
||||
try:
|
||||
regional_clients = {}
|
||||
service_regions = self.get_available_aws_service_regions(service)
|
||||
# Check if it is global service to gather only one region
|
||||
if global_service:
|
||||
if service_regions:
|
||||
if self.identity.profile_region in service_regions:
|
||||
service_regions = [self.identity.profile_region]
|
||||
service_regions = service_regions[:1]
|
||||
for region in service_regions:
|
||||
regional_client = self.session.session.client(
|
||||
service, region_name=region, config=self.session.session_config
|
||||
)
|
||||
regional_client.region = region
|
||||
regional_clients[region] = regional_client
|
||||
return regional_clients
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def get_available_aws_service_regions(self, service: str) -> list:
|
||||
# Get json locally
|
||||
actual_directory = pathlib.Path(os.path.dirname(os.path.realpath(__file__)))
|
||||
with open_file(f"{actual_directory}/{aws_services_json_file}") as f:
|
||||
data = parse_json_file(f)
|
||||
# Check if it is a subservice
|
||||
json_regions = data["services"][service]["regions"][self.identity.partition]
|
||||
if (
|
||||
self.identity.audited_regions
|
||||
): # Check for input aws audit_info.audited_regions
|
||||
regions = list(
|
||||
set(json_regions).intersection(self.identity.audited_regions)
|
||||
) # Get common regions between input and json
|
||||
else: # Get all regions from json of the service and partition
|
||||
regions = json_regions
|
||||
return regions
|
||||
|
||||
def get_aws_available_regions():
|
||||
try:
|
||||
actual_directory = pathlib.Path(os.path.dirname(os.path.realpath(__file__)))
|
||||
with open_file(f"{actual_directory}/{aws_services_json_file}") as f:
|
||||
data = parse_json_file(f)
|
||||
|
||||
regions = set()
|
||||
for service in data["services"].values():
|
||||
for partition in service["regions"]:
|
||||
for item in service["regions"][partition]:
|
||||
regions.add(item)
|
||||
return list(regions)
|
||||
except Exception as error:
|
||||
logger.error(f"{error.__class__.__name__}: {error}")
|
||||
return []
|
||||
|
||||
def get_checks_from_input_arn(audit_resources: list, provider: str) -> set:
|
||||
"""get_checks_from_input_arn gets the list of checks from the input arns"""
|
||||
checks_from_arn = set()
|
||||
is_subservice_in_checks = False
|
||||
# Handle if there are audit resources so only their services are executed
|
||||
if audit_resources:
|
||||
services_without_subservices = ["guardduty", "kms", "s3", "elb", "efs"]
|
||||
service_list = set()
|
||||
sub_service_list = set()
|
||||
for resource in audit_resources:
|
||||
service = resource.split(":")[2]
|
||||
sub_service = resource.split(":")[5].split("/")[0].replace("-", "_")
|
||||
# WAF Services does not have checks
|
||||
if service != "wafv2" and service != "waf":
|
||||
# Parse services when they are different in the ARNs
|
||||
if service == "lambda":
|
||||
service = "awslambda"
|
||||
elif service == "elasticloadbalancing":
|
||||
service = "elb"
|
||||
elif service == "elasticfilesystem":
|
||||
service = "efs"
|
||||
elif service == "logs":
|
||||
service = "cloudwatch"
|
||||
# Check if Prowler has checks in service
|
||||
try:
|
||||
list_modules(provider, service)
|
||||
except ModuleNotFoundError:
|
||||
# Service is not supported
|
||||
pass
|
||||
else:
|
||||
service_list.add(service)
|
||||
|
||||
# Get subservices to execute only applicable checks
|
||||
if service not in services_without_subservices:
|
||||
# Parse some specific subservices
|
||||
if service == "ec2":
|
||||
if sub_service == "security_group":
|
||||
sub_service = "securitygroup"
|
||||
if sub_service == "network_acl":
|
||||
sub_service = "networkacl"
|
||||
if sub_service == "image":
|
||||
sub_service = "ami"
|
||||
if service == "rds":
|
||||
if sub_service == "cluster_snapshot":
|
||||
sub_service = "snapshot"
|
||||
sub_service_list.add(sub_service)
|
||||
else:
|
||||
sub_service_list.add(service)
|
||||
checks = recover_checks_from_service(service_list, provider)
|
||||
|
||||
# Filter only checks with audited subservices
|
||||
for check in checks:
|
||||
if any(sub_service in check for sub_service in sub_service_list):
|
||||
if not (sub_service == "policy" and "password_policy" in check):
|
||||
checks_from_arn.add(check)
|
||||
is_subservice_in_checks = True
|
||||
|
||||
if not is_subservice_in_checks:
|
||||
checks_from_arn = checks
|
||||
|
||||
# Return final checks list
|
||||
return sorted(checks_from_arn)
|
||||
|
||||
def get_regions_from_audit_resources(audit_resources: list) -> set:
|
||||
"""get_regions_from_audit_resources gets the regions from the audit resources arns"""
|
||||
audited_regions = set()
|
||||
for resource in audit_resources:
|
||||
region = resource.split(":")[3]
|
||||
if region:
|
||||
audited_regions.add(region)
|
||||
return audited_regions
|
||||
|
||||
def get_tagged_resources(self, input_resource_tags: list):
|
||||
"""
|
||||
get_tagged_resources returns a list of the resources that are going to be scanned based on the given input tags
|
||||
"""
|
||||
try:
|
||||
resource_tags = []
|
||||
tagged_resources = []
|
||||
for tag in input_resource_tags:
|
||||
key = tag.split("=")[0]
|
||||
value = tag.split("=")[1]
|
||||
resource_tags.append({"Key": key, "Values": [value]})
|
||||
# Get Resources with resource_tags for all regions
|
||||
for regional_client in self.generate_regional_clients(
|
||||
"resourcegroupstaggingapi"
|
||||
).values():
|
||||
try:
|
||||
get_resources_paginator = regional_client.get_paginator(
|
||||
"get_resources"
|
||||
)
|
||||
for page in get_resources_paginator.paginate(
|
||||
TagFilters=resource_tags
|
||||
):
|
||||
for resource in page["ResourceTagMappingList"]:
|
||||
tagged_resources.append(resource["ResourceARN"])
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
sys.exit(1)
|
||||
else:
|
||||
return tagged_resources
|
||||
|
||||
def get_default_region(self, service: str) -> str:
|
||||
"""get_default_region gets the default region based on the profile and audited service regions"""
|
||||
service_regions = self.get_available_aws_service_regions(service)
|
||||
default_region = (
|
||||
self.get_global_region()
|
||||
) # global region of the partition when all regions are audited and there is no profile region
|
||||
if self.identity.profile_region in service_regions:
|
||||
# return profile region only if it is audited
|
||||
default_region = self.identity.profile_region
|
||||
# return first audited region if specific regions are audited
|
||||
elif self.identity.audited_regions:
|
||||
default_region = self.identity.audited_regions[0]
|
||||
return default_region
|
||||
|
||||
def get_global_region(self) -> str:
|
||||
"""get_global_region gets the global region based on the audited partition"""
|
||||
global_region = "us-east-1"
|
||||
if self.identity.partition == "aws-cn":
|
||||
global_region = "cn-north-1"
|
||||
elif self.identity.partition == "aws-us-gov":
|
||||
global_region = "us-gov-east-1"
|
||||
elif "aws-iso" in self.identity.partition:
|
||||
global_region = "aws-iso-global"
|
||||
return global_region
|
||||
|
||||
def __input_role_mfa_token_and_code__() -> tuple[str]:
|
||||
"""input_role_mfa_token_and_code ask for the AWS MFA ARN and TOTP and returns it."""
|
||||
mfa_ARN = input("Enter ARN of MFA: ")
|
||||
mfa_TOTP = input("Enter MFA code: ")
|
||||
return (mfa_ARN.strip(), mfa_TOTP.strip())
|
||||
|
||||
def __set_session_config__(self, aws_retries_max_attempts: bool):
|
||||
session_config = Config(
|
||||
retries={"max_attempts": 3, "mode": "standard"},
|
||||
user_agent_extra=BOTO3_USER_AGENT_EXTRA,
|
||||
)
|
||||
if aws_retries_max_attempts:
|
||||
# Create the new config
|
||||
config = Config(
|
||||
retries={
|
||||
"max_attempts": aws_retries_max_attempts,
|
||||
"mode": "standard",
|
||||
},
|
||||
)
|
||||
# Merge the new configuration
|
||||
session_config = self.session.session_config.merge(config)
|
||||
|
||||
return session_config
|
||||
|
||||
def __assume_role__(
|
||||
self,
|
||||
session,
|
||||
sts_endpoint_region: str,
|
||||
) -> dict:
|
||||
try:
|
||||
assume_role_arguments = {
|
||||
"RoleArn": self.assumed_role.assumed_role_info.role_arn,
|
||||
"RoleSessionName": "ProwlerAsessmentSession",
|
||||
"DurationSeconds": self.assumed_role.assumed_role_info.session_duration,
|
||||
}
|
||||
|
||||
# Set the info to assume the role from the partition, account and role name
|
||||
if self.assumed_role.assumed_role_info.external_id:
|
||||
assume_role_arguments[
|
||||
"ExternalId"
|
||||
] = self.assumed_role.assumed_role_info.external_id
|
||||
|
||||
if self.assumed_role.assumed_role_info.mfa_enabled:
|
||||
mfa_ARN, mfa_TOTP = self.__input_role_mfa_token_and_code__()
|
||||
assume_role_arguments["SerialNumber"] = mfa_ARN
|
||||
assume_role_arguments["TokenCode"] = mfa_TOTP
|
||||
|
||||
# Set the STS Endpoint Region
|
||||
if sts_endpoint_region is None:
|
||||
sts_endpoint_region = AWS_STS_GLOBAL_ENDPOINT_REGION
|
||||
|
||||
sts_client = create_sts_session(session, sts_endpoint_region)
|
||||
assumed_credentials = sts_client.assume_role(**assume_role_arguments)
|
||||
except Exception as error:
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
return assumed_credentials
|
||||
@@ -2,7 +2,7 @@ from boto3 import session
|
||||
from botocore.config import Config
|
||||
|
||||
from prowler.providers.aws.config import BOTO3_USER_AGENT_EXTRA
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Assume_Role, AWS_Audit_Info
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info, AWSAssumeRole
|
||||
|
||||
# Default Current Audit Info
|
||||
current_audit_info = AWS_Audit_Info(
|
||||
@@ -25,7 +25,7 @@ current_audit_info = AWS_Audit_Info(
|
||||
profile=None,
|
||||
profile_region=None,
|
||||
credentials=None,
|
||||
assumed_role_info=AWS_Assume_Role(
|
||||
assumed_role_info=AWSAssumeRole(
|
||||
role_arn=None,
|
||||
session_duration=None,
|
||||
external_id=None,
|
||||
|
||||
@@ -7,7 +7,7 @@ from botocore.config import Config
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWS_Credentials:
|
||||
class AWSCredentials:
|
||||
aws_access_key_id: str
|
||||
aws_session_token: str
|
||||
aws_secret_access_key: str
|
||||
@@ -15,7 +15,7 @@ class AWS_Credentials:
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWS_Assume_Role:
|
||||
class AWSAssumeRole:
|
||||
role_arn: str
|
||||
session_duration: int
|
||||
external_id: str
|
||||
@@ -23,7 +23,7 @@ class AWS_Assume_Role:
|
||||
|
||||
|
||||
@dataclass
|
||||
class AWS_Organizations_Info:
|
||||
class AWSOrganizationsInfo:
|
||||
account_details_email: str
|
||||
account_details_name: str
|
||||
account_details_arn: str
|
||||
@@ -44,12 +44,12 @@ class AWS_Audit_Info:
|
||||
audited_partition: str
|
||||
profile: str
|
||||
profile_region: str
|
||||
credentials: AWS_Credentials
|
||||
credentials: AWSCredentials
|
||||
mfa_enabled: bool
|
||||
assumed_role_info: AWS_Assume_Role
|
||||
assumed_role_info: AWSAssumeRole
|
||||
audited_regions: list
|
||||
audit_resources: list
|
||||
organizations_metadata: AWS_Organizations_Info
|
||||
audit_metadata: Optional[Any] = None
|
||||
organizations_metadata: AWSOrganizationsInfo
|
||||
audit_metadata: Optional[Any]
|
||||
audit_config: Optional[dict] = None
|
||||
ignore_unused_services: bool = False
|
||||
|
||||
@@ -8,7 +8,7 @@ from prowler.providers.aws.config import AWS_STS_GLOBAL_ENDPOINT_REGION
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||
|
||||
|
||||
def validate_aws_credentials(
|
||||
def validate_AWSCredentials(
|
||||
session: session, input_regions: list, sts_endpoint_region: str = None
|
||||
) -> dict:
|
||||
try:
|
||||
@@ -38,7 +38,7 @@ def validate_aws_credentials(
|
||||
return caller_identity
|
||||
|
||||
|
||||
def print_aws_credentials(audit_info: AWS_Audit_Info):
|
||||
def print_AWSCredentials(audit_info: AWS_Audit_Info):
|
||||
# Beautify audited regions, set "all" if there is no filter region
|
||||
regions = (
|
||||
", ".join(audit_info.audited_regions)
|
||||
|
||||
@@ -3,12 +3,12 @@ import sys
|
||||
from boto3 import client
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Organizations_Info
|
||||
from prowler.providers.aws.lib.audit_info.models import AWSOrganizationsInfo
|
||||
|
||||
|
||||
def get_organizations_metadata(
|
||||
metadata_account: str, assumed_credentials: dict
|
||||
) -> AWS_Organizations_Info:
|
||||
) -> AWSOrganizationsInfo:
|
||||
try:
|
||||
organizations_client = client(
|
||||
"organizations",
|
||||
@@ -30,7 +30,7 @@ def get_organizations_metadata(
|
||||
account_details_tags = ""
|
||||
for tag in list_tags_for_resource["Tags"]:
|
||||
account_details_tags += tag["Key"] + ":" + tag["Value"] + ","
|
||||
organizations_info = AWS_Organizations_Info(
|
||||
organizations_info = AWSOrganizationsInfo(
|
||||
account_details_email=organizations_metadata["Account"]["Email"],
|
||||
account_details_name=organizations_metadata["Account"]["Name"],
|
||||
account_details_arn=organizations_metadata["Account"]["Arn"],
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import threading
|
||||
|
||||
from prowler.providers.aws.aws_provider import (
|
||||
generate_regional_clients,
|
||||
get_default_region,
|
||||
)
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||
from prowler.providers.aws.aws_provider_new import AwsProvider
|
||||
|
||||
|
||||
class AWSService:
|
||||
@@ -15,18 +11,18 @@ class AWSService:
|
||||
- Also handles if the AWS Service is Global
|
||||
"""
|
||||
|
||||
def __init__(self, service: str, audit_info: AWS_Audit_Info, global_service=False):
|
||||
def __init__(self, service: str, provider: AwsProvider, global_service=False):
|
||||
# Audit Information
|
||||
self.audit_info = audit_info
|
||||
self.audited_account = audit_info.audited_account
|
||||
self.audited_account_arn = audit_info.audited_account_arn
|
||||
self.audited_partition = audit_info.audited_partition
|
||||
self.audit_resources = audit_info.audit_resources
|
||||
self.audited_checks = audit_info.audit_metadata.expected_checks
|
||||
self.audit_config = audit_info.audit_config
|
||||
self.provider = provider
|
||||
self.audited_account = provider.identity.account
|
||||
self.audited_account_arn = provider.identity.account_arn
|
||||
self.audited_partition = provider.identity.partition
|
||||
self.audit_resources = provider.audit_resources
|
||||
self.audited_checks = provider.audit_metadata.expected_checks
|
||||
self.audit_config = provider.audit_config
|
||||
|
||||
# AWS Session
|
||||
self.session = audit_info.audit_session
|
||||
self.session = provider.session.session
|
||||
|
||||
# We receive the service using __class__.__name__ or the service name in lowercase
|
||||
# e.g.: AccessAnalyzer --> we need a lowercase string, so service.lower()
|
||||
@@ -34,14 +30,14 @@ class AWSService:
|
||||
|
||||
# Generate Regional Clients
|
||||
if not global_service:
|
||||
self.regional_clients = generate_regional_clients(
|
||||
self.service, audit_info, global_service
|
||||
self.regional_clients = provider.generate_regional_clients(
|
||||
self.service, global_service
|
||||
)
|
||||
|
||||
# Get a single region and client if the service needs it (e.g. AWS Global Service)
|
||||
# We cannot include this within an else because some services needs both the regional_clients
|
||||
# and a single client like S3
|
||||
self.region = get_default_region(self.service, audit_info)
|
||||
self.region = provider.get_default_region(self.service)
|
||||
self.client = self.session.client(self.service, self.region)
|
||||
|
||||
def __get_session__(self):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_service import (
|
||||
AccessAnalyzer,
|
||||
)
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
accessanalyzer_client = AccessAnalyzer(current_audit_info)
|
||||
accessanalyzer_client = AccessAnalyzer(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## AccessAnalyzer
|
||||
class AccessAnalyzer(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.analyzers = []
|
||||
self.__threading_call__(self.__list_analyzers__)
|
||||
self.__list_findings__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.account.account_service import Account
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
account_client = Account(current_audit_info)
|
||||
account_client = Account(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
|
||||
class Account(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.number_of_contacts = 4
|
||||
self.contact_base = self.__get_contact_information__()
|
||||
self.contacts_billing = self.__get_alternate_contact__("BILLING")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.acm.acm_service import ACM
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
acm_client = ACM(current_audit_info)
|
||||
acm_client = ACM(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## ACM
|
||||
class ACM(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.certificates = []
|
||||
self.__threading_call__(self.__list_certificates__)
|
||||
self.__describe_certificates__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.apigateway.apigateway_service import APIGateway
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
apigateway_client = APIGateway(current_audit_info)
|
||||
apigateway_client = APIGateway(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## APIGateway
|
||||
class APIGateway(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.rest_apis = []
|
||||
self.__threading_call__(self.__get_rest_apis__)
|
||||
self.__get_authorizers__()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.apigatewayv2.apigatewayv2_service import (
|
||||
ApiGatewayV2,
|
||||
)
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
apigatewayv2_client = ApiGatewayV2(current_audit_info)
|
||||
apigatewayv2_client = ApiGatewayV2(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## ApiGatewayV2
|
||||
class ApiGatewayV2(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.apis = []
|
||||
self.__threading_call__(self.__get_apis__)
|
||||
self.__get_authorizers__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.appstream.appstream_service import AppStream
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
appstream_client = AppStream(current_audit_info)
|
||||
appstream_client = AppStream(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## AppStream
|
||||
class AppStream(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.fleets = []
|
||||
self.__threading_call__(self.__describe_fleets__)
|
||||
self.__list_tags_for_resource__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.athena.athena_service import Athena
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
athena_client = Athena(current_audit_info)
|
||||
athena_client = Athena(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## Athena
|
||||
class Athena(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.workgroups = {}
|
||||
self.__threading_call__(self.__list_workgroups__)
|
||||
self.__get_workgroups__()
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class athena_workgroup_encryption(Check):
|
||||
# Only check for enabled and used workgroups (has recent queries)
|
||||
if (
|
||||
workgroup.state == "ENABLED" and workgroup.queries
|
||||
) or not athena_client.audit_info.ignore_unused_services:
|
||||
) or not athena_client.provider.ignore_unused_services:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = workgroup.region
|
||||
report.resource_id = workgroup.name
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class athena_workgroup_enforce_configuration(Check):
|
||||
# Only check for enabled and used workgroups (has recent queries)
|
||||
if (
|
||||
workgroup.state == "ENABLED" and workgroup.queries
|
||||
) or not athena_client.audit_info.ignore_unused_services:
|
||||
) or not athena_client.provider.ignore_unused_services:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = workgroup.region
|
||||
report.resource_id = workgroup.name
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.autoscaling.autoscaling_service import AutoScaling
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
autoscaling_client = AutoScaling(current_audit_info)
|
||||
autoscaling_client = AutoScaling(get_global_provider())
|
||||
|
||||
@@ -7,9 +7,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## AutoScaling
|
||||
class AutoScaling(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.launch_configurations = []
|
||||
self.__threading_call__(self.__describe_launch_configurations__)
|
||||
self.groups = []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.awslambda.awslambda_service import Lambda
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
awslambda_client = Lambda(current_audit_info)
|
||||
awslambda_client = Lambda(get_global_provider())
|
||||
|
||||
@@ -15,9 +15,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## Lambda
|
||||
class Lambda(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.functions = {}
|
||||
self.__threading_call__(self.__list_functions__)
|
||||
self.__list_tags_for_resource__()
|
||||
@@ -26,7 +26,7 @@ class Lambda(AWSService):
|
||||
# awslambda_function_no_secrets_in_code check is set
|
||||
if (
|
||||
"awslambda_function_no_secrets_in_code"
|
||||
in audit_info.audit_metadata.expected_checks
|
||||
in provider.audit_metadata.expected_checks
|
||||
):
|
||||
self.__threading_call__(self.__get_function__)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.backup.backup_service import Backup
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
backup_client = Backup(current_audit_info)
|
||||
backup_client = Backup(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## Backup
|
||||
class Backup(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.backup_vaults = []
|
||||
self.__threading_call__(self.__list_backup_vaults__)
|
||||
self.backup_plans = []
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.cloudformation.cloudformation_service import (
|
||||
CloudFormation,
|
||||
)
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
cloudformation_client = CloudFormation(current_audit_info)
|
||||
cloudformation_client = CloudFormation(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## CloudFormation
|
||||
class CloudFormation(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.stacks = []
|
||||
self.__threading_call__(self.__describe_stacks__)
|
||||
self.__describe_stack__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.cloudfront.cloudfront_service import CloudFront
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
cloudfront_client = CloudFront(current_audit_info)
|
||||
cloudfront_client = CloudFront(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## CloudFront
|
||||
class CloudFront(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info, global_service=True)
|
||||
super().__init__(__class__.__name__, provider, global_service=True)
|
||||
self.distributions = {}
|
||||
self.__list_distributions__(self.client, self.region)
|
||||
self.__get_distribution_config__(self.client, self.distributions, self.region)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.cloudtrail.cloudtrail_service import Cloudtrail
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
cloudtrail_client = Cloudtrail(current_audit_info)
|
||||
cloudtrail_client = Cloudtrail(get_global_provider())
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ class cloudtrail_s3_dataevents_read_enabled(Check):
|
||||
report.status_extended = f"Trail {trail.name} from home region {trail.home_region} has an advanced data event selector to record all S3 object-level API operations."
|
||||
findings.append(report)
|
||||
if not findings and (
|
||||
s3_client.buckets or not cloudtrail_client.audit_info.ignore_unused_services
|
||||
s3_client.buckets or not cloudtrail_client.provider.ignore_unused_services
|
||||
):
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = cloudtrail_client.region
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ class cloudtrail_s3_dataevents_write_enabled(Check):
|
||||
report.status_extended = f"Trail {trail.name} from home region {trail.home_region} has an advanced data event selector to record all S3 object-level API operations."
|
||||
findings.append(report)
|
||||
if not findings and (
|
||||
s3_client.buckets or not cloudtrail_client.audit_info.ignore_unused_services
|
||||
s3_client.buckets or not cloudtrail_client.provider.ignore_unused_services
|
||||
):
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = cloudtrail_client.region
|
||||
|
||||
@@ -11,9 +11,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################### CLOUDTRAIL
|
||||
class Cloudtrail(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.trails = []
|
||||
self.__threading_call__(self.__get_trails__)
|
||||
self.__get_trail_status__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_service import CloudWatch
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
cloudwatch_client = CloudWatch(current_audit_info)
|
||||
cloudwatch_client = CloudWatch(get_global_provider())
|
||||
|
||||
@@ -11,9 +11,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## CloudWatch
|
||||
class CloudWatch(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.metric_alarms = []
|
||||
self.__threading_call__(self.__describe_alarms__)
|
||||
self.__list_tags_for_resource__()
|
||||
@@ -64,16 +64,16 @@ class CloudWatch(AWSService):
|
||||
|
||||
################## CloudWatch Logs
|
||||
class Logs(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.metric_filters = []
|
||||
self.log_groups = []
|
||||
self.__threading_call__(self.__describe_metric_filters__)
|
||||
self.__threading_call__(self.__describe_log_groups__)
|
||||
if (
|
||||
"cloudwatch_log_group_no_secrets_in_logs"
|
||||
in audit_info.audit_metadata.expected_checks
|
||||
in provider.audit_metadata.expected_checks
|
||||
):
|
||||
self.events_per_log_group_threshold = (
|
||||
1000 # The threshold for number of events to return per log group.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.cloudwatch.cloudwatch_service import Logs
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
logs_client = Logs(current_audit_info)
|
||||
logs_client = Logs(get_global_provider())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.codeartifact.codeartifact_service import (
|
||||
CodeArtifact,
|
||||
)
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
codeartifact_client = CodeArtifact(current_audit_info)
|
||||
codeartifact_client = CodeArtifact(get_global_provider())
|
||||
|
||||
@@ -11,9 +11,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## CodeArtifact
|
||||
class CodeArtifact(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
# repositories is a dictionary containing all the codeartifact service information
|
||||
self.repositories = {}
|
||||
self.__threading_call__(self.__list_repositories__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
codebuild_client = Codebuild(current_audit_info)
|
||||
codebuild_client = Codebuild(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################### Codebuild
|
||||
class Codebuild(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.projects = []
|
||||
self.__threading_call__(self.__list_projects__)
|
||||
self.__list_builds_for_project__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.config.config_service import Config
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
config_client = Config(current_audit_info)
|
||||
config_client = Config(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## Config
|
||||
class Config(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.recorders = []
|
||||
self.__threading_call__(self.__describe_configuration_recorder_status__)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.directoryservice.directoryservice_service import (
|
||||
DirectoryService,
|
||||
)
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
directoryservice_client = DirectoryService(current_audit_info)
|
||||
directoryservice_client = DirectoryService(get_global_provider())
|
||||
|
||||
@@ -12,9 +12,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## DirectoryService
|
||||
class DirectoryService(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__("ds", audit_info)
|
||||
super().__init__("ds", provider)
|
||||
self.directories = {}
|
||||
self.__threading_call__(self.__describe_directories__)
|
||||
self.__threading_call__(self.__list_log_subscriptions__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.dlm.dlm_service import DLM
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
dlm_client = DLM(current_audit_info)
|
||||
dlm_client = DLM(get_global_provider())
|
||||
|
||||
@@ -6,9 +6,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## Data Lifecycle Manager
|
||||
class DLM(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.lifecycle_policies = {}
|
||||
self.__threading_call__(self.__get_lifecycle_policies__)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.documentdb.documentdb_service import DocumentDB
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
documentdb_client = DocumentDB(current_audit_info)
|
||||
documentdb_client = DocumentDB(get_global_provider())
|
||||
|
||||
@@ -9,10 +9,10 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## DocumentDB
|
||||
class DocumentDB(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
self.service_name = "docdb"
|
||||
super().__init__(self.service_name, audit_info)
|
||||
super().__init__(self.service_name, provider)
|
||||
self.db_instances = {}
|
||||
self.__threading_call__(self.__describe_db_instances__)
|
||||
self.__list_tags_for_resource__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.drs.drs_service import DRS
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
drs_client = DRS(current_audit_info)
|
||||
drs_client = DRS(get_global_provider())
|
||||
|
||||
@@ -8,9 +8,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## DRS (Elastic Disaster Recovery Service)
|
||||
class DRS(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.drs_services = []
|
||||
self.__threading_call__(self.__describe_jobs__)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_service import DAX
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
dax_client = DAX(current_audit_info)
|
||||
dax_client = DAX(get_global_provider())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_service import DynamoDB
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
dynamodb_client = DynamoDB(current_audit_info)
|
||||
dynamodb_client = DynamoDB(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## DynamoDB
|
||||
class DynamoDB(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.tables = []
|
||||
self.__threading_call__(self.__list_tables__)
|
||||
self.__describe_table__()
|
||||
@@ -121,9 +121,9 @@ class DynamoDB(AWSService):
|
||||
|
||||
################## DynamoDB DAX
|
||||
class DAX(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.clusters = []
|
||||
self.__threading_call__(self.__describe_clusters__)
|
||||
self.__list_tags_for_resource__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.ec2.ec2_service import EC2
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
ec2_client = EC2(current_audit_info)
|
||||
ec2_client = EC2(get_global_provider())
|
||||
|
||||
+1
-2
@@ -15,8 +15,7 @@ class ec2_ebs_default_encryption(Check):
|
||||
report.status_extended = "EBS Default Encryption is activated."
|
||||
findings.append(report)
|
||||
elif (
|
||||
not ec2_client.audit_info.ignore_unused_services
|
||||
or ebs_encryption.volumes
|
||||
not ec2_client.provider.ignore_unused_services or ebs_encryption.volumes
|
||||
):
|
||||
report.status = "FAIL"
|
||||
report.status_extended = "EBS Default Encryption is not activated."
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_networkacl_allow_ingress_any_port(Check):
|
||||
check_port = 0
|
||||
for network_acl in ec2_client.network_acls:
|
||||
if (
|
||||
not ec2_client.audit_info.ignore_unused_services
|
||||
not ec2_client.provider.ignore_unused_services
|
||||
or network_acl.region in ec2_client.regions_with_sgs
|
||||
):
|
||||
# If some entry allows it, that ACL is not securely configured
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_networkacl_allow_ingress_tcp_port_22(Check):
|
||||
check_port = 22
|
||||
for network_acl in ec2_client.network_acls:
|
||||
if (
|
||||
not ec2_client.audit_info.ignore_unused_services
|
||||
not ec2_client.provider.ignore_unused_services
|
||||
or network_acl.region in ec2_client.regions_with_sgs
|
||||
):
|
||||
# If some entry allows it, that ACL is not securely configured
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_networkacl_allow_ingress_tcp_port_3389(Check):
|
||||
check_port = 3389
|
||||
for network_acl in ec2_client.network_acls:
|
||||
if (
|
||||
not ec2_client.audit_info.ignore_unused_services
|
||||
not ec2_client.provider.ignore_unused_services
|
||||
or network_acl.region in ec2_client.regions_with_sgs
|
||||
):
|
||||
# If some entry allows it, that ACL is not securely configured
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_any_port(Check):
|
||||
findings = []
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018(
|
||||
check_ports = [27017, 27018]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21(Check)
|
||||
check_ports = [20, 21]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22(Check):
|
||||
check_ports = [22]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389(Check):
|
||||
check_ports = [3389]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9
|
||||
check_ports = [7199, 9160, 8888]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_ki
|
||||
check_ports = [9200, 9300, 5601]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092(Check
|
||||
check_ports = [9092]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211(
|
||||
check_ports = [11211]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306(Check
|
||||
check_ports = [3306]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483
|
||||
check_ports = [1521, 2483]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432(Ch
|
||||
check_ports = [5432]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379(Check
|
||||
check_ports = [6379]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_
|
||||
check_ports = [1433, 1434]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23(Check)
|
||||
check_ports = [23]
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ class ec2_securitygroup_allow_wide_open_public_ipv4(Check):
|
||||
cidr_treshold = 24
|
||||
for security_group in ec2_client.security_groups:
|
||||
# Check if ignoring flag is set and if the VPC and the SG is in use
|
||||
if not ec2_client.audit_info.ignore_unused_services or (
|
||||
if not ec2_client.provider.ignore_unused_services or (
|
||||
security_group.vpc_id in vpc_client.vpcs
|
||||
and vpc_client.vpcs[security_group.vpc_id].in_use
|
||||
and len(security_group.network_interfaces) > 0
|
||||
|
||||
@@ -12,9 +12,9 @@ from prowler.providers.aws.services.ec2.lib.security_groups import check_securit
|
||||
|
||||
################## EC2
|
||||
class EC2(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.instances = []
|
||||
self.__threading_call__(self.__describe_instances__)
|
||||
self.__get_instance_user_data__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.ecr.ecr_service import ECR
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
ecr_client = ECR(current_audit_info)
|
||||
ecr_client = ECR(get_global_provider())
|
||||
|
||||
@@ -12,10 +12,10 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################################ ECR
|
||||
class ECR(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
self.registry_id = audit_info.audited_account
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.registry_id = self.audited_account
|
||||
self.registries = {}
|
||||
self.__threading_call__(self.__describe_registries_and_repositories__)
|
||||
self.__threading_call__(self.__describe_repository_policies__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.ecs.ecs_service import ECS
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
ecs_client = ECS(current_audit_info)
|
||||
ecs_client = ECS(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################################ ECS
|
||||
class ECS(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.task_definitions = []
|
||||
self.__threading_call__(self.__list_task_definitions__)
|
||||
self.__describe_task_definition__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.efs.efs_service import EFS
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
efs_client = EFS(current_audit_info)
|
||||
efs_client = EFS(get_global_provider())
|
||||
|
||||
@@ -11,9 +11,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################### EFS
|
||||
class EFS(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.filesystems = []
|
||||
self.__threading_call__(self.__describe_file_systems__)
|
||||
self.__describe_file_system_policies__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.eks.eks_service import EKS
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
eks_client = EKS(current_audit_info)
|
||||
eks_client = EKS(get_global_provider())
|
||||
|
||||
@@ -4,16 +4,14 @@ from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.scan_filters.scan_filters import is_resource_filtered
|
||||
from prowler.providers.aws.aws_provider import generate_regional_clients
|
||||
from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
|
||||
################################ EKS
|
||||
class EKS(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
self.regional_clients = generate_regional_clients(self.service, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.clusters = []
|
||||
self.__threading_call__(self.__list_clusters__)
|
||||
self.__describe_cluster__(self.regional_clients)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.elasticache.elasticache_service import ElastiCache
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
elasticache_client = ElastiCache(current_audit_info)
|
||||
elasticache_client = ElastiCache(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################################ Elasticache
|
||||
class ElastiCache(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.clusters = {}
|
||||
self.__threading_call__(self.__describe_cache_clusters__)
|
||||
self.__threading_call__(self.__describe_cache_subnet_groups__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.elb.elb_service import ELB
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
elb_client = ELB(current_audit_info)
|
||||
elb_client = ELB(get_global_provider())
|
||||
|
||||
@@ -9,9 +9,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################### ELB
|
||||
class ELB(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.loadbalancers = []
|
||||
self.__threading_call__(self.__describe_load_balancers__)
|
||||
self.__threading_call__(self.__describe_load_balancer_attributes__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
elbv2_client = ELBv2(current_audit_info)
|
||||
elbv2_client = ELBv2(get_global_provider())
|
||||
|
||||
@@ -10,9 +10,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################### ELBv2
|
||||
class ELBv2(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.loadbalancersv2 = []
|
||||
self.__threading_call__(self.__describe_load_balancers__)
|
||||
self.listeners = []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.emr.emr_service import EMR
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
emr_client = EMR(current_audit_info)
|
||||
emr_client = EMR(get_global_provider())
|
||||
|
||||
@@ -11,9 +11,9 @@ from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
################## EMR
|
||||
class EMR(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.clusters = {}
|
||||
self.block_public_access_configuration = {}
|
||||
self.__threading_call__(self.__list_clusters__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.fms.fms_service import FMS
|
||||
from prowler.providers.common.common import get_global_provider
|
||||
|
||||
fms_client = FMS(current_audit_info)
|
||||
fms_client = FMS(get_global_provider())
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user