fix(global_services): handle global regions correctly (#1594)

Co-authored-by: sergargar <sergio@verica.io>
Co-authored-by: Pepe Fagoaga <pepe@verica.io>
This commit is contained in:
Sergio Garcia
2022-12-23 12:32:31 +01:00
committed by GitHub
parent 3cfe1b8376
commit d9dc6c0a49
25 changed files with 789 additions and 223 deletions

View File

@@ -103,40 +103,16 @@ def assume_role(audit_info: AWS_Audit_Info) -> dict:
return assumed_credentials return assumed_credentials
def generate_regional_clients(service: str, audit_info: AWS_Audit_Info) -> dict: def generate_regional_clients(
service: str, audit_info: AWS_Audit_Info, global_service: bool = False
) -> dict:
try:
regional_clients = {} regional_clients = {}
# Get json locally # Get json locally
actual_directory = os.path.dirname(os.path.realpath(__file__)) actual_directory = os.path.dirname(os.path.realpath(__file__))
f = open_file(f"{actual_directory}/{aws_services_json_file}") f = open_file(f"{actual_directory}/{aws_services_json_file}")
data = parse_json_file(f) data = parse_json_file(f)
# Check if it is a subservice # Check if it is a subservice
if service == "accessanalyzer":
json_regions = data["services"]["iam"]["regions"][audit_info.audited_partition]
elif service == "apigatewayv2":
json_regions = data["services"]["apigateway"]["regions"][
audit_info.audited_partition
]
elif service == "macie2":
json_regions = data["services"]["macie"]["regions"][
audit_info.audited_partition
]
elif service == "logs":
json_regions = data["services"]["cloudwatch"]["regions"][
audit_info.audited_partition
]
elif service == "dax":
json_regions = data["services"]["dynamodb"]["regions"][
audit_info.audited_partition
]
elif service == "glacier":
json_regions = data["services"]["s3"]["regions"][audit_info.audited_partition]
elif service == "opensearch":
json_regions = data["services"]["es"]["regions"][audit_info.audited_partition]
elif service == "elbv2":
json_regions = data["services"]["elb"]["regions"][audit_info.audited_partition]
elif service == "wafv2" or service == "waf-regional":
json_regions = data["services"]["waf"]["regions"][audit_info.audited_partition]
else:
json_regions = data["services"][service]["regions"][ json_regions = data["services"][service]["regions"][
audit_info.audited_partition audit_info.audited_partition
] ]
@@ -146,15 +122,20 @@ def generate_regional_clients(service: str, audit_info: AWS_Audit_Info) -> dict:
) # Get common regions between input and json ) # Get common regions between input and json
else: # Get all regions from json of the service and partition else: # Get all regions from json of the service and partition
regions = json_regions regions = json_regions
# Check if it is global service to gather only one region
if global_service:
if regions:
if audit_info.profile_region in regions:
regions = [audit_info.profile_region]
regions = regions[:1]
for region in regions: for region in regions:
regional_client = audit_info.audit_session.client(service, region_name=region) regional_client = audit_info.audit_session.client(
service, region_name=region
)
regional_client.region = region regional_client.region = region
regional_clients[region] = regional_client regional_clients[region] = regional_client
return regional_clients return regional_clients
except Exception as error:
logger.error(
def get_region_global_service(audit_info: AWS_Audit_Info) -> str: f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
# Check if global service to send the finding to first audited region )
if audit_info.audited_regions:
return audit_info.audited_regions[0]
return audit_info.profile_region

View File

@@ -1,5 +1,45 @@
{ {
"services": { "services": {
"accessanalyzer": {
"regions": {
"aws": [
"ap-south-2",
"ap-southeast-1",
"ap-southeast-2",
"ap-southeast-3",
"eu-north-1",
"us-west-1",
"af-south-1",
"ap-northeast-1",
"ca-central-1",
"eu-central-1",
"eu-south-2",
"eu-west-2",
"me-central-1",
"me-south-1",
"us-east-2",
"us-west-2",
"ap-east-1",
"ap-northeast-2",
"ap-northeast-3",
"ap-south-1",
"eu-central-2",
"eu-south-1",
"eu-west-1",
"eu-west-3",
"sa-east-1",
"us-east-1"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-east-1",
"us-gov-west-1"
]
}
},
"acm": { "acm": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -211,6 +251,46 @@
] ]
} }
}, },
"apigatewayv2": {
"regions": {
"aws": [
"af-south-1",
"ap-east-1",
"ap-northeast-3",
"eu-central-1",
"eu-north-1",
"eu-south-2",
"sa-east-1",
"us-east-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-southeast-2",
"ap-southeast-3",
"eu-south-1",
"eu-west-1",
"eu-west-2",
"me-central-1",
"us-east-2",
"ap-south-1",
"ap-south-2",
"ap-southeast-1",
"ca-central-1",
"eu-central-2",
"eu-west-3",
"me-south-1",
"us-west-1",
"us-west-2"
],
"aws-cn": [
"cn-northwest-1",
"cn-north-1"
],
"aws-us-gov": [
"us-gov-east-1",
"us-gov-west-1"
]
}
},
"appflow": { "appflow": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -1567,6 +1647,46 @@
] ]
} }
}, },
"dax": {
"regions": {
"aws": [
"ap-south-2",
"ap-southeast-3",
"ca-central-1",
"eu-central-1",
"eu-central-2",
"eu-north-1",
"eu-west-2",
"me-south-1",
"ap-east-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-southeast-2",
"eu-south-2",
"eu-west-1",
"me-central-1",
"us-east-2",
"us-west-2",
"af-south-1",
"ap-northeast-3",
"ap-south-1",
"ap-southeast-1",
"eu-south-1",
"eu-west-3",
"sa-east-1",
"us-east-1",
"us-west-1"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-east-1",
"us-gov-west-1"
]
}
},
"deepcomposer": { "deepcomposer": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -2271,6 +2391,46 @@
] ]
} }
}, },
"elbv2": {
"regions": {
"aws": [
"ap-northeast-1",
"ap-south-2",
"eu-north-1",
"eu-south-1",
"eu-west-2",
"me-central-1",
"me-south-1",
"us-east-2",
"us-west-2",
"ap-northeast-2",
"ap-northeast-3",
"ap-south-1",
"ap-southeast-3",
"eu-central-1",
"eu-central-2",
"eu-west-1",
"eu-west-3",
"sa-east-1",
"us-east-1",
"af-south-1",
"ap-east-1",
"ap-southeast-1",
"ap-southeast-2",
"ca-central-1",
"eu-south-2",
"us-west-1"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-east-1",
"us-gov-west-1"
]
}
},
"emr": { "emr": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -2769,6 +2929,46 @@
"aws-us-gov": {} "aws-us-gov": {}
} }
}, },
"glacier": {
"regions": {
"aws": [
"ap-east-1",
"ap-northeast-1",
"eu-central-1",
"eu-west-2",
"eu-west-3",
"me-central-1",
"sa-east-1",
"us-west-1",
"ap-northeast-3",
"ap-south-1",
"ap-south-2",
"ap-southeast-1",
"ap-southeast-2",
"ap-southeast-3",
"eu-south-2",
"us-east-1",
"af-south-1",
"ap-northeast-2",
"ca-central-1",
"eu-central-2",
"eu-north-1",
"eu-south-1",
"eu-west-1",
"me-south-1",
"us-east-2",
"us-west-2"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-east-1",
"us-gov-west-1"
]
}
},
"globalaccelerator": { "globalaccelerator": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -3511,19 +3711,20 @@
"lex-runtime": { "lex-runtime": {
"regions": { "regions": {
"aws": [ "aws": [
"af-south-1",
"ap-northeast-1", "ap-northeast-1",
"ap-northeast-2",
"ap-southeast-1", "ap-southeast-1",
"ap-southeast-2", "ca-central-1",
"eu-central-1", "eu-central-1",
"eu-west-1", "eu-west-1",
"eu-west-2", "eu-west-2",
"us-east-1", "us-east-1",
"us-west-2" "us-west-2",
"ap-southeast-2"
], ],
"aws-cn": {}, "aws-cn": {},
"aws-us-gov": [ "aws-us-gov": {}
"us-gov-west-1"
]
} }
}, },
"license-manager": { "license-manager": {
@@ -3584,6 +3785,46 @@
"aws-us-gov": {} "aws-us-gov": {}
} }
}, },
"logs": {
"regions": {
"aws": [
"ap-northeast-2",
"ap-south-2",
"ca-central-1",
"me-central-1",
"me-south-1",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-1",
"us-west-2",
"af-south-1",
"ap-east-1",
"ap-northeast-1",
"ap-northeast-3",
"ap-southeast-3",
"eu-central-2",
"eu-north-1",
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"eu-central-1",
"eu-south-1",
"eu-south-2",
"eu-west-1",
"eu-west-2",
"eu-west-3"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-west-1",
"us-gov-east-1"
]
}
},
"lookoutmetrics": { "lookoutmetrics": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -3691,6 +3932,35 @@
"aws-us-gov": {} "aws-us-gov": {}
} }
}, },
"macie2": {
"regions": {
"aws": [
"ap-northeast-1",
"ap-northeast-2",
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"eu-central-1",
"eu-north-1",
"eu-west-1",
"us-east-1",
"us-east-2",
"af-south-1",
"ap-east-1",
"ap-northeast-3",
"ca-central-1",
"eu-west-2",
"eu-west-3",
"me-south-1",
"sa-east-1",
"us-west-1",
"us-west-2",
"eu-south-1"
],
"aws-cn": {},
"aws-us-gov": {}
}
},
"managedblockchain": { "managedblockchain": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -4113,7 +4383,7 @@
"ap-northeast-3", "ap-northeast-3",
"ap-southeast-1", "ap-southeast-1",
"ap-southeast-2", "ap-southeast-2",
"eu-west-2", "ap-southeast-3",
"eu-west-3", "eu-west-3",
"me-south-1", "me-south-1",
"us-east-2", "us-east-2",
@@ -4122,11 +4392,12 @@
"ap-northeast-2", "ap-northeast-2",
"ap-south-1", "ap-south-1",
"ca-central-1", "ca-central-1",
"eu-central-1",
"eu-north-1", "eu-north-1",
"eu-south-1", "eu-south-1",
"eu-west-1", "eu-west-1",
"eu-west-2",
"us-east-1", "us-east-1",
"eu-central-1",
"sa-east-1", "sa-east-1",
"us-west-2" "us-west-2"
], ],
@@ -4151,6 +4422,46 @@
"aws-us-gov": {} "aws-us-gov": {}
} }
}, },
"opensearch": {
"regions": {
"aws": [
"ap-east-1",
"ap-south-1",
"ap-southeast-2",
"eu-south-1",
"eu-south-2",
"eu-west-3",
"us-west-1",
"us-west-2",
"af-south-1",
"ap-south-2",
"ca-central-1",
"eu-central-1",
"eu-central-2",
"eu-north-1",
"eu-west-1",
"us-east-1",
"us-east-2",
"ap-northeast-1",
"ap-northeast-2",
"ap-northeast-3",
"ap-southeast-1",
"ap-southeast-3",
"eu-west-2",
"me-central-1",
"me-south-1",
"sa-east-1"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-west-1",
"us-gov-east-1"
]
}
},
"opsworks": { "opsworks": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -4762,6 +5073,43 @@
"aws-us-gov": {} "aws-us-gov": {}
} }
}, },
"route53domains": {
"regions": {
"aws": [
"ap-east-1",
"ap-northeast-3",
"ap-south-1",
"eu-central-1",
"eu-central-2",
"eu-west-1",
"eu-west-2",
"sa-east-1",
"us-west-1",
"af-south-1",
"ap-northeast-2",
"ap-south-2",
"ap-southeast-1",
"ap-southeast-2",
"ap-southeast-3",
"eu-north-1",
"eu-south-1",
"eu-south-2",
"eu-west-3",
"ap-northeast-1",
"ca-central-1",
"me-central-1",
"me-south-1",
"us-east-1",
"us-east-2",
"us-west-2"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": {}
}
},
"s3": { "s3": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -4802,6 +5150,46 @@
] ]
} }
}, },
"s3control": {
"regions": {
"aws": [
"ap-east-1",
"ap-northeast-1",
"eu-central-1",
"eu-west-2",
"eu-west-3",
"me-central-1",
"sa-east-1",
"us-west-1",
"ap-northeast-3",
"ap-south-1",
"ap-south-2",
"ap-southeast-1",
"ap-southeast-2",
"ap-southeast-3",
"eu-south-2",
"us-east-1",
"af-south-1",
"ap-northeast-2",
"ca-central-1",
"eu-central-2",
"eu-north-1",
"eu-south-1",
"eu-west-1",
"me-south-1",
"us-east-2",
"us-west-2"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-east-1",
"us-gov-west-1"
]
}
},
"sagemaker": { "sagemaker": {
"regions": { "regions": {
"aws": [ "aws": [
@@ -5004,6 +5392,7 @@
"ap-southeast-1", "ap-southeast-1",
"ap-southeast-2", "ap-southeast-2",
"eu-south-1", "eu-south-1",
"eu-south-2",
"eu-west-2", "eu-west-2",
"eu-west-3", "eu-west-3",
"us-west-1", "us-west-1",
@@ -5013,14 +5402,16 @@
"ca-central-1", "ca-central-1",
"eu-central-1", "eu-central-1",
"eu-north-1", "eu-north-1",
"me-south-1",
"us-east-2", "us-east-2",
"us-west-2", "us-west-2",
"ap-east-1", "ap-east-1",
"ap-northeast-2", "ap-northeast-2",
"ap-south-1", "ap-south-1",
"ap-south-2",
"eu-central-2",
"eu-west-1", "eu-west-1",
"me-central-1", "me-central-1",
"me-south-1",
"sa-east-1", "sa-east-1",
"us-east-1" "us-east-1"
], ],
@@ -5029,8 +5420,8 @@
"cn-northwest-1" "cn-northwest-1"
], ],
"aws-us-gov": [ "aws-us-gov": [
"us-gov-west-1", "us-gov-east-1",
"us-gov-east-1" "us-gov-west-1"
] ]
} }
}, },
@@ -5915,6 +6306,78 @@
] ]
} }
}, },
"waf-regional": {
"regions": {
"aws": [
"af-south-1",
"ap-east-1",
"ap-southeast-3",
"eu-central-1",
"eu-north-1",
"eu-west-1",
"eu-west-2",
"me-south-1",
"us-west-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-northeast-3",
"ap-southeast-1",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-2",
"ap-south-1",
"ap-southeast-2",
"ca-central-1",
"eu-south-1",
"eu-west-3"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-west-1",
"us-gov-east-1"
]
}
},
"wafv2": {
"regions": {
"aws": [
"af-south-1",
"ap-east-1",
"ap-southeast-3",
"eu-central-1",
"eu-north-1",
"eu-west-1",
"eu-west-2",
"me-south-1",
"us-west-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-northeast-3",
"ap-southeast-1",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-2",
"ap-south-1",
"ap-southeast-2",
"ca-central-1",
"eu-south-1",
"eu-west-3"
],
"aws-cn": [
"cn-north-1",
"cn-northwest-1"
],
"aws-us-gov": [
"us-gov-west-1",
"us-gov-east-1"
]
}
},
"wam": { "wam": {
"regions": { "regions": {
"aws": [ "aws": [

View File

@@ -1,5 +1,4 @@
################## Account ################## Account
from prowler.providers.aws.aws_provider import get_region_global_service
class Account: class Account:
@@ -7,7 +6,7 @@ class Account:
self.service = "account" self.service = "account"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.region = get_region_global_service(audit_info) self.region = audit_info.profile_region
def __get_session__(self): def __get_session__(self):
return self.session return self.session

View File

@@ -2,7 +2,7 @@ from dataclasses import dataclass
from enum import Enum from enum import Enum
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import get_region_global_service from prowler.providers.aws.aws_provider import generate_regional_clients
################## CloudFront ################## CloudFront
@@ -11,8 +11,13 @@ class CloudFront:
self.service = "cloudfront" self.service = "cloudfront"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.client = self.session.client(self.service) global_client = generate_regional_clients(
self.region = get_region_global_service(audit_info) self.service, audit_info, global_service=True
)
self.distributions = {}
if global_client:
self.client = list(global_client.values())[0]
self.region = self.client.region
self.distributions = self.__list_distributions__(self.client, self.region) self.distributions = self.__list_distributions__(self.client, self.region)
self.distributions = self.__get_distribution_config__( self.distributions = self.__get_distribution_config__(
self.client, self.distributions, self.region self.client, self.distributions, self.region

View File

@@ -3,10 +3,7 @@ import threading
from dataclasses import dataclass from dataclasses import dataclass
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import ( from prowler.providers.aws.aws_provider import generate_regional_clients
generate_regional_clients,
get_region_global_service,
)
################### CLOUDTRAIL ################### CLOUDTRAIL
@@ -15,7 +12,7 @@ class Cloudtrail:
self.service = "cloudtrail" self.service = "cloudtrail"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.region = get_region_global_service(audit_info) self.region = audit_info.profile_region
self.regional_clients = generate_regional_clients(self.service, audit_info) self.regional_clients = generate_regional_clients(self.service, audit_info)
self.trails = [] self.trails = []
self.__threading_call__(self.__get_trails__) self.__threading_call__(self.__get_trails__)

View File

@@ -9,12 +9,13 @@ class GlobalAccelerator:
self.service = "globalaccelerator" self.service = "globalaccelerator"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.accelerators = {}
if audit_info.audited_partition == "aws":
# Global Accelerator is a global service that supports endpoints in multiple AWS Regions # Global Accelerator is a global service that supports endpoints in multiple AWS Regions
# but you must specify the US West (Oregon) Region to create, update, or otherwise work with accelerators. # but you must specify the US West (Oregon) Region to create, update, or otherwise work with accelerators.
# That is, for example, specify --region us-west-2 on AWS CLI commands. # That is, for example, specify --region us-west-2 on AWS CLI commands.
self.region = "us-west-2" self.region = "us-west-2"
self.client = self.session.client(self.service, self.region) self.client = self.session.client(self.service, self.region)
self.accelerators = {}
self.__list_accelerators__() self.__list_accelerators__()
def __get_session__(self): def __get_session__(self):

View File

@@ -3,7 +3,7 @@ from dataclasses import dataclass
from datetime import datetime from datetime import datetime
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import get_region_global_service from prowler.providers.aws.aws_provider import generate_regional_clients
################## IAM ################## IAM
@@ -14,7 +14,11 @@ class IAM:
self.account = audit_info.audited_account self.account = audit_info.audited_account
self.partition = audit_info.audited_partition self.partition = audit_info.audited_partition
self.client = self.session.client(self.service) self.client = self.session.client(self.service)
self.region = get_region_global_service(audit_info) global_client = generate_regional_clients(
self.service, audit_info, global_service=True
)
self.client = list(global_client.values())[0]
self.region = self.client.region
self.users = self.__get_users__() self.users = self.__get_users__()
self.roles = self.__get_roles__() self.roles = self.__get_roles__()
self.account_summary = self.__get_account_summary__() self.account_summary = self.__get_account_summary__()

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel from pydantic import BaseModel
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import get_region_global_service from prowler.providers.aws.aws_provider import generate_regional_clients
################## Route53 ################## Route53
@@ -10,9 +10,13 @@ class Route53:
self.service = "route53" self.service = "route53"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_partition = audit_info.audited_partition self.audited_partition = audit_info.audited_partition
self.client = self.session.client(self.service)
self.region = get_region_global_service(audit_info)
self.hosted_zones = {} self.hosted_zones = {}
global_client = generate_regional_clients(
self.service, audit_info, global_service=True
)
if global_client:
self.client = list(global_client.values())[0]
self.region = self.client.region
self.__list_hosted_zones__() self.__list_hosted_zones__()
self.__list_query_logging_configs__() self.__list_query_logging_configs__()
@@ -84,11 +88,12 @@ class Route53Domains:
self.service = "route53domains" self.service = "route53domains"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.domains = {}
if audit_info.audited_partition == "aws":
# Route53Domains is a global service that supports endpoints in multiple AWS Regions # Route53Domains is a global service that supports endpoints in multiple AWS Regions
# but you must specify the US East (N. Virginia) Region to create, update, or otherwise work with domains. # but you must specify the US East (N. Virginia) Region to create, update, or otherwise work with domains.
self.region = "us-east-1" self.region = "us-east-1"
self.client = self.session.client(self.service, self.region) self.client = self.session.client(self.service, self.region)
self.domains = {}
self.__list_domains__() self.__list_domains__()
self.__get_domain_detail__() self.__get_domain_detail__()

View File

@@ -3,10 +3,7 @@ import threading
from dataclasses import dataclass from dataclasses import dataclass
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import ( from prowler.providers.aws.aws_provider import generate_regional_clients
generate_regional_clients,
get_region_global_service,
)
################## S3 ################## S3
@@ -203,8 +200,12 @@ class S3Control:
self.service = "s3control" self.service = "s3control"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.region = get_region_global_service(audit_info) global_client = generate_regional_clients(
self.client = self.session.client(self.service, self.region) self.service, audit_info, global_service=True
)
if global_client:
self.client = list(global_client.values())[0]
self.region = self.client.region
self.account_public_access_block = self.__get_public_access_block__() self.account_public_access_block = self.__get_public_access_block__()
def __get_session__(self): def __get_session__(self):

View File

@@ -1,48 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7170="7.170"
CHECK_TITLE_extra7170="[extra7170] Check if internet-facing application load balancers are protected by AWS Shield Advanced"
CHECK_SCORED_extra7170="NOT_SCORED"
CHECK_CIS_LEVEL_extra7170="EXTRA"
CHECK_SEVERITY_extra7170="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7170="AwsElasticLoadBalancingV2LoadBalancer"
CHECK_ALTERNATE_check7170="extra7170"
CHECK_SERVICENAME_extra7170="shield"
CHECK_RISK_extra7170='AWS Shield Advanced provides expanded DDoS attack protection for your resources'
CHECK_REMEDIATION_extra7170='Add as a protected resource in AWS Shield Advanced.'
CHECK_DOC_extra7170='https://docs.aws.amazon.com/waf/latest/developerguide/configure-new-protection.html'
CHECK_CAF_EPIC_extra7170='Infrastructure security'
extra7170() {
if [[ "$($AWSCLI $PROFILE_OPT shield get-subscription-state --output text)" == "ACTIVE" ]]; then
for regx in $REGIONS; do
LIST_OF_APPLICATION_LOAD_BALANCERS=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Type == `application` && Scheme == `internet-facing`].[LoadBalancerName,LoadBalancerArn]' --output text)
if [[ $LIST_OF_APPLICATION_LOAD_BALANCERS ]]; then
while read -r alb; do
ALB_NAME=$(echo $alb | awk '{ print $1; }')
ALB_ARN=$(echo $alb | awk '{ print $2; }')
if $AWSCLI $PROFILE_OPT shield describe-protection --resource-arn $ALB_ARN >/dev/null 2>&1; then
textPass "$regx: ALB $ALB_NAME is protected by AWS Shield Advanced" "$regx" "$ALB_NAME"
else
textFail "$regx: ALB $ALB_NAME is not protected by AWS Shield Advanced" "$regx" "$ALB_NAME"
fi
done <<<"$LIST_OF_APPLICATION_LOAD_BALANCERS"
else
textInfo "$regx: no application load balancers found" "$regx"
fi
done
else
textInfo "No AWS Shield Advanced subscription found. Skipping check."
fi
}

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel from pydantic import BaseModel
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import get_region_global_service from prowler.providers.aws.aws_provider import generate_regional_clients
################### Shield ################### Shield
@@ -10,10 +10,16 @@ class Shield:
self.service = "shield" self.service = "shield"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account self.audited_account = audit_info.audited_account
self.client = self.session.client(self.service) global_client = generate_regional_clients(
self.region = get_region_global_service(audit_info) self.service, audit_info, global_service=True
self.enabled = self.__get_subscription_state__() )
self.protections = {} self.protections = {}
self.enabled = False
if global_client:
self.client = list(global_client.values())[0]
self.region = self.client.region
self.enabled = self.__get_subscription_state__()
if self.enabled:
self.__list_protections__() self.__list_protections__()
def __get_session__(self): def __get_session__(self):

View File

@@ -7,17 +7,22 @@ from prowler.providers.aws.services.trustedadvisor.trustedadvisor_client import
class trustedadvisor_errors_and_warnings(Check): class trustedadvisor_errors_and_warnings(Check):
def execute(self): def execute(self):
findings = [] findings = []
if trustedadvisor_client.enabled:
if trustedadvisor_client.checks: if trustedadvisor_client.checks:
for check in trustedadvisor_client.checks: for check in trustedadvisor_client.checks:
report = Check_Report_AWS(self.metadata()) report = Check_Report_AWS(self.metadata())
report.region = check.region report.region = check.region
report.resource_id = check.id report.resource_id = check.id
report.status = "FAIL" report.status = "FAIL"
report.status_extended = ( report.status_extended = f"Trusted Advisor check {check.name} is in state {check.status}."
f"Trusted Advisor check {check.name} is in state {check.status}."
)
if check.status == "ok": if check.status == "ok":
report.status = "PASS" report.status = "PASS"
findings.append(report) findings.append(report)
else:
report = Check_Report_AWS(self.metadata())
report.status = "INFO"
report.status_extended = "Amazon Web Services Premium Support Subscription is required to use this service."
report.resource_id = trustedadvisor_client.account
findings.append(report)
return findings return findings

View File

@@ -1,10 +1,9 @@
import threading
from typing import Optional from typing import Optional
from botocore.client import ClientError
from pydantic import BaseModel from pydantic import BaseModel
from prowler.lib.logger import logger from prowler.lib.logger import logger
from prowler.providers.aws.aws_provider import generate_regional_clients
################################ TrustedAdvisor ################################ TrustedAdvisor
@@ -12,54 +11,64 @@ class TrustedAdvisor:
def __init__(self, audit_info): def __init__(self, audit_info):
self.service = "support" self.service = "support"
self.session = audit_info.audit_session self.session = audit_info.audit_session
self.regional_clients = generate_regional_clients(self.service, audit_info) self.account = audit_info.audited_account
self.checks = [] self.checks = []
self.__threading_call__(self.__describe_trusted_advisor_checks__) self.enabled = True
self.__threading_call__(self.__describe_trusted_advisor_check_result__) # Support API is not available in China Partition
# But only in us-east-1 or us-gov-west-1 https://docs.aws.amazon.com/general/latest/gr/awssupport.html
if audit_info.audited_partition != "aws-cn":
if audit_info.audited_partition == "aws":
support_region = "us-east-1"
else:
support_region = "us-gov-west-1"
self.client = audit_info.audit_session.client(
self.service, region_name=support_region
)
self.client.region = self.region = support_region
self.__describe_trusted_advisor_checks__()
self.__describe_trusted_advisor_check_result__()
def __get_session__(self): def __get_session__(self):
return self.session return self.session
def __threading_call__(self, call): def __describe_trusted_advisor_checks__(self):
threads = []
for regional_client in self.regional_clients.values():
threads.append(threading.Thread(target=call, args=(regional_client,)))
for t in threads:
t.start()
for t in threads:
t.join()
def __describe_trusted_advisor_checks__(self, regional_client):
logger.info("TrustedAdvisor - Describing Checks...") logger.info("TrustedAdvisor - Describing Checks...")
try: try:
for check in regional_client.describe_trusted_advisor_checks(language="en")[ for check in self.client.describe_trusted_advisor_checks(language="en")[
"checks" "checks"
]: ]:
self.checks.append( self.checks.append(
Check( Check(
id=check["id"], id=check["id"],
name=check["name"], name=check["name"],
region=regional_client.region, region=self.client.region,
) )
) )
except ClientError as error:
if error.response["Error"]["Code"] == "SubscriptionRequiredException":
self.enabled = False
else:
logger.error(
f"{self.client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
except Exception as error: except Exception as error:
logger.error( logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" f"{self.client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
) )
def __describe_trusted_advisor_check_result__(self, regional_client): def __describe_trusted_advisor_check_result__(self):
logger.info("TrustedAdvisor - Describing Check Result...") logger.info("TrustedAdvisor - Describing Check Result...")
try: try:
for check in self.checks: for check in self.checks:
if check.region == regional_client.region: if check.region == self.client.region:
response = regional_client.describe_trusted_advisor_check_result( response = self.client.describe_trusted_advisor_check_result(
checkId=check.id checkId=check.id
) )
if "result" in response: if "result" in response:
check.status = response["result"]["status"] check.status = response["result"]["status"]
except Exception as error: except Exception as error:
logger.error( logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" f"{self.client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
) )

View File

@@ -2,7 +2,7 @@ import boto3
import sure # noqa import sure # noqa
from moto import mock_iam, mock_sts from moto import mock_iam, mock_sts
from prowler.providers.aws.aws_provider import assume_role, get_region_global_service from prowler.providers.aws.aws_provider import assume_role, generate_regional_clients
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_Assume_Role, AWS_Audit_Info
ACCOUNT_ID = 123456789012 ACCOUNT_ID = 123456789012
@@ -82,24 +82,85 @@ class Test_AWS_Provider:
21 + 1 + len(sessionName) 21 + 1 + len(sessionName)
) )
def test_get_region_global_service(self): def test_generate_regional_clients(self):
# Create mock audit_info # New Boto3 session with the previously create user
input_audit_info = AWS_Audit_Info( session = boto3.session.Session(
region_name="us-east-1",
)
audited_regions = ["eu-west-1", "us-east-1"]
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
original_session=None, original_session=None,
audit_session=None, audit_session=session,
audited_account="123456789012", audited_account=None,
audited_identity_arn="test-arn",
audited_user_id="test",
audited_partition="aws", audited_partition="aws",
profile="default", audited_identity_arn=None,
profile_region="eu-west-1", audited_user_id=None,
profile=None,
profile_region=None,
credentials=None, credentials=None,
assumed_role_info=None, assumed_role_info=None,
audited_regions=["eu-west-2", "eu-west-1"], audited_regions=audited_regions,
organizations_metadata=None, organizations_metadata=None,
) )
generate_regional_clients_response = generate_regional_clients(
assert ( "ec2", audit_info
get_region_global_service(input_audit_info)
== input_audit_info.audited_regions[0]
) )
assert set(generate_regional_clients_response.keys()) == set(audited_regions)
def test_generate_regional_clients_global_service(self):
# New Boto3 session with the previously create user
session = boto3.session.Session(
region_name="us-east-1",
)
audited_regions = ["eu-west-1", "us-east-1"]
profile_region = "us-east-1"
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
original_session=None,
audit_session=session,
audited_account=None,
audited_partition="aws",
audited_identity_arn=None,
audited_user_id=None,
profile=None,
profile_region=profile_region,
credentials=None,
assumed_role_info=None,
audited_regions=audited_regions,
organizations_metadata=None,
)
generate_regional_clients_response = generate_regional_clients(
"route53", audit_info, global_service=True
)
assert list(generate_regional_clients_response.keys()) == [profile_region]
def test_generate_regional_clients_cn_partition(self):
# New Boto3 session with the previously create user
session = boto3.session.Session(
region_name="us-east-1",
)
audited_regions = ["cn-northwest-1", "cn-north-1"]
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
original_session=None,
audit_session=session,
audited_account=None,
audited_partition="aws-cn",
audited_identity_arn=None,
audited_user_id=None,
profile=None,
profile_region=None,
credentials=None,
assumed_role_info=None,
audited_regions=audited_regions,
organizations_metadata=None,
)
generate_regional_clients_response = generate_regional_clients(
"shield", audit_info, global_service=True
)
# Shield does not exist in China
assert generate_regional_clients_response == {}

View File

@@ -17,6 +17,8 @@ class Test_iam_administrator_access_with_mfa_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client", "prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -55,6 +57,8 @@ class Test_iam_administrator_access_with_mfa_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client", "prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -88,6 +92,8 @@ class Test_iam_administrator_access_with_mfa_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client", "prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -123,6 +129,8 @@ class Test_iam_administrator_access_with_mfa_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client", "prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -182,6 +190,8 @@ class Test_iam_administrator_access_with_mfa_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client", "prowler.providers.aws.services.iam.iam_administrator_access_with_mfa.iam_administrator_access_with_mfa.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -18,6 +18,8 @@ class Test_iam_avoid_root_usage:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client", "prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -51,6 +53,8 @@ class Test_iam_avoid_root_usage:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client", "prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -83,6 +87,8 @@ class Test_iam_avoid_root_usage:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client", "prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -115,6 +121,8 @@ class Test_iam_avoid_root_usage:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client", "prowler.providers.aws.services.iam.iam_avoid_root_usage.iam_avoid_root_usage.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -44,6 +44,8 @@ nTTxU4a7x1naFxzYXK1iQ1vMARKMjDb19QEJIEJKZlDK4uS7yMlf1nFS
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_check_saml_providers_sts.iam_check_saml_providers_sts.iam_client", "prowler.providers.aws.services.iam.iam_check_saml_providers_sts.iam_check_saml_providers_sts.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -18,6 +18,8 @@ class Test_iam_disable_30_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -48,6 +50,8 @@ class Test_iam_disable_30_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -75,6 +79,8 @@ class Test_iam_disable_30_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -18,6 +18,8 @@ class Test_iam_disable_45_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -48,6 +50,8 @@ class Test_iam_disable_45_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -75,6 +79,8 @@ class Test_iam_disable_45_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -18,6 +18,8 @@ class Test_iam_disable_90_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -48,6 +50,8 @@ class Test_iam_disable_90_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -75,6 +79,8 @@ class Test_iam_disable_90_days_credentials_test:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -24,6 +24,8 @@ class Test_iam_no_custom_policy_permissive_role_assumption:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client", "prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -59,6 +61,8 @@ class Test_iam_no_custom_policy_permissive_role_assumption:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client", "prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -97,6 +101,8 @@ class Test_iam_no_custom_policy_permissive_role_assumption:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client", "prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -132,6 +138,8 @@ class Test_iam_no_custom_policy_permissive_role_assumption:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client", "prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),
@@ -179,6 +187,8 @@ class Test_iam_no_custom_policy_permissive_role_assumption:
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
current_audit_info.audited_partition = "aws"
with mock.patch( with mock.patch(
"prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client", "prowler.providers.aws.services.iam.iam_no_custom_policy_permissive_role_assumption.iam_no_custom_policy_permissive_role_assumption.iam_client",
new=IAM(current_audit_info), new=IAM(current_audit_info),

View File

@@ -2,11 +2,11 @@ import json
from json import dumps from json import dumps
from boto3 import client, session from boto3 import client, session
from freezegun import freeze_time
from moto import mock_iam from moto import mock_iam
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
from prowler.providers.aws.services.iam.iam_service import IAM from prowler.providers.aws.services.iam.iam_service import IAM
from freezegun import freeze_time
AWS_ACCOUNT_NUMBER = 123456789012 AWS_ACCOUNT_NUMBER = 123456789012
TEST_DATETIME = "2023-01-01T12:01:01+00:00" TEST_DATETIME = "2023-01-01T12:01:01+00:00"
@@ -23,10 +23,10 @@ class Test_IAM_Service:
), ),
audited_account=None, audited_account=None,
audited_user_id=None, audited_user_id=None,
audited_partition=None, audited_partition="aws",
audited_identity_arn=None, audited_identity_arn=None,
profile=None, profile=None,
profile_region=None, profile_region="us-east-1",
credentials=None, credentials=None,
assumed_role_info=None, assumed_role_info=None,
audited_regions=None, audited_regions=None,

View File

@@ -14,6 +14,8 @@ class Test_trustedadvisor_errors_and_warnings:
def test_no_detectors(self): def test_no_detectors(self):
trustedadvisor_client = mock.MagicMock trustedadvisor_client = mock.MagicMock
trustedadvisor_client.checks = [] trustedadvisor_client.checks = []
trustedadvisor_client.enabled = False
trustedadvisor_client.account = AWS_ACCOUNT_NUMBER
with mock.patch( with mock.patch(
"prowler.providers.aws.services.trustedadvisor.trustedadvisor_service.TrustedAdvisor", "prowler.providers.aws.services.trustedadvisor.trustedadvisor_service.TrustedAdvisor",
trustedadvisor_client, trustedadvisor_client,
@@ -24,11 +26,16 @@ class Test_trustedadvisor_errors_and_warnings:
check = trustedadvisor_errors_and_warnings() check = trustedadvisor_errors_and_warnings()
result = check.execute() result = check.execute()
assert len(result) == 0 assert len(result) == 1
assert (
result[0].status_extended
== "Amazon Web Services Premium Support Subscription is required to use this service."
)
def test_trustedadvisor_all_passed_checks(self): def test_trustedadvisor_all_passed_checks(self):
trustedadvisor_client = mock.MagicMock trustedadvisor_client = mock.MagicMock
trustedadvisor_client.checks = [] trustedadvisor_client.checks = []
trustedadvisor_client.enabled = True
trustedadvisor_client.checks.append( trustedadvisor_client.checks.append(
Check( Check(
id="check1", id="check1",
@@ -55,6 +62,7 @@ class Test_trustedadvisor_errors_and_warnings:
def test_trustedadvisor_error_check(self): def test_trustedadvisor_error_check(self):
trustedadvisor_client = mock.MagicMock trustedadvisor_client = mock.MagicMock
trustedadvisor_client.checks = [] trustedadvisor_client.checks = []
trustedadvisor_client.enabled = True
trustedadvisor_client.checks.append( trustedadvisor_client.checks.append(
Check( Check(
id="check1", id="check1",

View File

@@ -21,17 +21,7 @@ def mock_make_api_call(self, operation_name, kwarg):
return make_api_call(self, operation_name, kwarg) return make_api_call(self, operation_name, kwarg)
def mock_generate_regional_clients(service, audit_info):
regional_client = audit_info.audit_session.client(service, region_name=AWS_REGION)
regional_client.region = AWS_REGION
return {AWS_REGION: regional_client}
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) @patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
@patch(
"prowler.providers.aws.services.trustedadvisor.trustedadvisor_service.generate_regional_clients",
new=mock_generate_regional_clients,
)
class Test_TrustedAdvisor_Service: class Test_TrustedAdvisor_Service:
# Mocked Audit Info # Mocked Audit Info
def set_mocked_audit_info(self): def set_mocked_audit_info(self):
@@ -46,7 +36,7 @@ class Test_TrustedAdvisor_Service:
audited_partition="aws", audited_partition="aws",
audited_identity_arn=None, audited_identity_arn=None,
profile=None, profile=None,
profile_region=None, profile_region=AWS_REGION,
credentials=None, credentials=None,
assumed_role_info=None, assumed_role_info=None,
audited_regions=None, audited_regions=None,
@@ -64,8 +54,7 @@ class Test_TrustedAdvisor_Service:
def test_client(self): def test_client(self):
audit_info = self.set_mocked_audit_info() audit_info = self.set_mocked_audit_info()
trustedadvisor = TrustedAdvisor(audit_info) trustedadvisor = TrustedAdvisor(audit_info)
for reg_client in trustedadvisor.regional_clients.values(): assert trustedadvisor.client.__class__.__name__ == "Support"
assert reg_client.__class__.__name__ == "Support"
# Test TrustedAdvisor session # Test TrustedAdvisor session
def test__get_session__(self): def test__get_session__(self):

View File

@@ -20,7 +20,8 @@ logging.basicConfig(
with request.urlopen(aws_services_json_url) as url: # Get the AWS regions matrix online with request.urlopen(aws_services_json_url) as url: # Get the AWS regions matrix online
logging.info(f"Downloading JSON from {aws_services_json_url}") logging.info(f"Downloading JSON from {aws_services_json_url}")
original_matrix_regions_aws = json.loads(url.read().decode()) original_matrix_regions_aws = json.loads(url.read().decode())
parsed__matrix_regions_aws = f"{os.path.dirname(os.path.realpath(__name__))}/prowler/providers/aws/aws_regions_by_service.json" parsed_matrix_regions_aws = f"{os.path.dirname(os.path.realpath(__name__))}/prowler/providers/aws/aws_regions_by_service.json"
# JSON objects # JSON objects
regions_by_service = {} regions_by_service = {}
@@ -66,7 +67,38 @@ for item in original_matrix_regions_aws["prices"]:
logging.info("Storing final JSON") logging.info("Storing final JSON")
regions_by_service["services"] = services regions_by_service["services"] = services
# Include the regions for the subservices and the services not present
logging.info("Updating subservices and the services not present in the original matrix")
# accessanalyzer --> iam
regions_by_service["services"]["accessanalyzer"] = regions_by_service["services"]["iam"]
# apigatewayv2 --> apigateway
regions_by_service["services"]["apigatewayv2"] = regions_by_service["services"][
"apigateway"
]
# macie2 --> macie
regions_by_service["services"]["macie2"] = regions_by_service["services"]["macie"]
# logs --> cloudwatch
regions_by_service["services"]["logs"] = regions_by_service["services"]["cloudwatch"]
# dax --> dynamodb
regions_by_service["services"]["dax"] = regions_by_service["services"]["dynamodb"]
# glacier --> s3
regions_by_service["services"]["glacier"] = regions_by_service["services"]["s3"]
# opensearch --> es
regions_by_service["services"]["opensearch"] = regions_by_service["services"]["es"]
# elbv2 --> elb
regions_by_service["services"]["elbv2"] = regions_by_service["services"]["elb"]
# route53domains --> route53
regions_by_service["services"]["route53domains"] = regions_by_service["services"][
"route53"
]
# s3control --> s3
regions_by_service["services"]["s3control"] = regions_by_service["services"]["s3"]
# wafv2 --> waf
regions_by_service["services"]["wafv2"] = regions_by_service["services"]["waf"]
# waf-regional --> waf
regions_by_service["services"]["waf-regional"] = regions_by_service["services"]["waf"]
# Write to file # Write to file
logging.info(f"Writing {parsed__matrix_regions_aws}") logging.info(f"Writing {parsed_matrix_regions_aws}")
with open(parsed__matrix_regions_aws, "w") as outfile: with open(parsed_matrix_regions_aws, "w") as outfile:
json.dump(regions_by_service, outfile, indent=2, sort_keys=True) json.dump(regions_by_service, outfile, indent=2, sort_keys=True)