mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(cognito): add Amazon Cognito service (#3060)
This commit is contained in:
@@ -240,6 +240,8 @@ def get_checks_from_input_arn(audit_resources: list, provider: str) -> set:
|
||||
service = "efs"
|
||||
elif service == "logs":
|
||||
service = "cloudwatch"
|
||||
elif service == "cognito":
|
||||
service = "cognito-idp"
|
||||
# Check if Prowler has checks in service
|
||||
try:
|
||||
list_modules(provider, service)
|
||||
|
||||
@@ -2195,6 +2195,36 @@
|
||||
"aws-us-gov": []
|
||||
}
|
||||
},
|
||||
"cognito": {
|
||||
"regions": {
|
||||
"aws": [
|
||||
"ap-northeast-1",
|
||||
"ap-northeast-2",
|
||||
"ap-northeast-3",
|
||||
"ap-south-1",
|
||||
"ap-southeast-1",
|
||||
"ap-southeast-2",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-north-1",
|
||||
"eu-south-1",
|
||||
"eu-west-1",
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
"il-central-1",
|
||||
"me-south-1",
|
||||
"sa-east-1",
|
||||
"us-east-1",
|
||||
"us-east-2",
|
||||
"us-west-1",
|
||||
"us-west-2"
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-us-gov": [
|
||||
"us-gov-west-1"
|
||||
]
|
||||
}
|
||||
},
|
||||
"cognito-identity": {
|
||||
"regions": {
|
||||
"aws": [
|
||||
@@ -10683,4 +10713,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0
prowler/providers/aws/services/cognito/__init__.py
Normal file
0
prowler/providers/aws/services/cognito/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from prowler.providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from prowler.providers.aws.services.cognito.cognito_service import CognitoIDP
|
||||
|
||||
cognito_idp_client = CognitoIDP(current_audit_info)
|
||||
122
prowler/providers/aws/services/cognito/cognito_service.py
Normal file
122
prowler/providers/aws/services/cognito/cognito_service.py
Normal file
@@ -0,0 +1,122 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
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.lib.service.service import AWSService
|
||||
|
||||
|
||||
################## CognitoIDP
|
||||
class CognitoIDP(AWSService):
|
||||
def __init__(self, audit_info):
|
||||
super().__init__("cognito-idp", audit_info)
|
||||
self.user_pools = {}
|
||||
self.__threading_call__(self.__list_user_pools__)
|
||||
self.__describe_user_pools__()
|
||||
self.__get_user_pool_mfa_config__()
|
||||
|
||||
def __list_user_pools__(self, regional_client):
|
||||
logger.info("Cognito - Listing User Pools...")
|
||||
try:
|
||||
user_pools_paginator = regional_client.get_paginator("list_user_pools")
|
||||
for page in user_pools_paginator.paginate(MaxResults=60):
|
||||
for user_pool in page["UserPools"]:
|
||||
arn = f"arn:{self.audited_partition}:cognito-idp:{regional_client.region}:{self.audited_account}:userpool/{user_pool['Id']}"
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(arn, self.audit_resources)
|
||||
):
|
||||
try:
|
||||
self.user_pools[arn] = UserPool(
|
||||
id=user_pool["Id"],
|
||||
arn=arn,
|
||||
name=user_pool["Name"],
|
||||
region=regional_client.region,
|
||||
last_modified=user_pool["LastModifiedDate"],
|
||||
creation_date=user_pool["CreationDate"],
|
||||
status=user_pool.get("Status", "Disabled"),
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __describe_user_pools__(self):
|
||||
logger.info("Cognito - Describing User Pools...")
|
||||
try:
|
||||
for user_pool in self.user_pools.values():
|
||||
try:
|
||||
user_pool_details = self.regional_clients[
|
||||
user_pool.region
|
||||
].describe_user_pool(UserPoolId=user_pool.id)["UserPool"]
|
||||
user_pool.password_policy = user_pool_details.get(
|
||||
"Policies", {}
|
||||
).get("PasswordPolicy", {})
|
||||
user_pool.deletion_protection = user_pool_details.get(
|
||||
"DeletionProtection", "INACTIVE"
|
||||
)
|
||||
user_pool.advanced_security_mode = user_pool_details.get(
|
||||
"UserPoolAddOns", {}
|
||||
).get("AdvancedSecurityMode", "OFF")
|
||||
user_pool.tags = [user_pool_details.get("UserPoolTags", "")]
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{user_pool.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{user_pool.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __get_user_pool_mfa_config__(self):
|
||||
logger.info("Cognito - Getting User Pool MFA Configuration...")
|
||||
try:
|
||||
for user_pool in self.user_pools.values():
|
||||
try:
|
||||
mfa_config = self.regional_clients[
|
||||
user_pool.region
|
||||
].get_user_pool_mfa_config(UserPoolId=user_pool.id)
|
||||
if mfa_config["MfaConfiguration"] != "OFF":
|
||||
user_pool.mfa_config = MFAConfig(
|
||||
sms_authentication=mfa_config.get(
|
||||
"SmsMfaConfiguration", {}
|
||||
),
|
||||
software_token_mfa_authentication=mfa_config.get(
|
||||
"SoftwareTokenMfaConfiguration", {}
|
||||
),
|
||||
status=mfa_config["MfaConfiguration"],
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{user_pool.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{user_pool.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
class MFAConfig(BaseModel):
|
||||
sms_authentication: Optional[dict]
|
||||
software_token_mfa_authentication: Optional[dict]
|
||||
status: str
|
||||
|
||||
|
||||
class UserPool(BaseModel):
|
||||
id: str
|
||||
arn: str
|
||||
name: str
|
||||
region: str
|
||||
advanced_security_mode: str = "OFF"
|
||||
deletion_protection: str = "INACTIVE"
|
||||
last_modified: datetime
|
||||
creation_date: datetime
|
||||
status: str
|
||||
password_policy: Optional[dict]
|
||||
mfa_config: Optional[MFAConfig]
|
||||
tags: Optional[list] = []
|
||||
@@ -256,6 +256,10 @@ def mock_recover_checks_from_aws_provider_rds_service(*_):
|
||||
]
|
||||
|
||||
|
||||
def mock_recover_checks_from_aws_provider_cognito_service(*_):
|
||||
return []
|
||||
|
||||
|
||||
class Test_Check:
|
||||
def test_load_check_metadata(self):
|
||||
test_cases = [
|
||||
@@ -565,6 +569,19 @@ class Test_Check:
|
||||
recovered_checks = get_checks_from_input_arn(audit_resources, provider)
|
||||
assert recovered_checks == expected_checks
|
||||
|
||||
@patch(
|
||||
"prowler.lib.check.check.recover_checks_from_provider",
|
||||
new=mock_recover_checks_from_aws_provider_cognito_service,
|
||||
)
|
||||
def test_get_checks_from_input_arn_cognito(self):
|
||||
audit_resources = [
|
||||
f"arn:aws:cognito-idp:us-east-1:{AWS_ACCOUNT_NUMBER}:userpool/test"
|
||||
]
|
||||
provider = "aws"
|
||||
expected_checks = []
|
||||
recovered_checks = get_checks_from_input_arn(audit_resources, provider)
|
||||
assert recovered_checks == expected_checks
|
||||
|
||||
@patch(
|
||||
"prowler.lib.check.check.recover_checks_from_provider",
|
||||
new=mock_recover_checks_from_aws_provider_ec2_service,
|
||||
|
||||
117
tests/providers/aws/services/cognito/cognito_service_test.py
Normal file
117
tests/providers/aws/services/cognito/cognito_service_test.py
Normal file
@@ -0,0 +1,117 @@
|
||||
from boto3 import client
|
||||
from moto import mock_cognitoidp
|
||||
|
||||
from prowler.providers.aws.services.cognito.cognito_service import CognitoIDP
|
||||
from tests.providers.aws.audit_info_utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_EU_WEST_1,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_audit_info,
|
||||
)
|
||||
|
||||
|
||||
class Test_Cognito_Service:
|
||||
# Test Cognito Service
|
||||
@mock_cognitoidp
|
||||
def test_service(self):
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito = CognitoIDP(audit_info)
|
||||
assert cognito.service == "cognito-idp"
|
||||
|
||||
# Test Cognito client
|
||||
@mock_cognitoidp
|
||||
def test_client(self):
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito = CognitoIDP(audit_info)
|
||||
for regional_client in cognito.regional_clients.values():
|
||||
assert regional_client.__class__.__name__ == "CognitoIdentityProvider"
|
||||
|
||||
# Test Cognito session
|
||||
@mock_cognitoidp
|
||||
def test__get_session__(self):
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito = CognitoIDP(audit_info)
|
||||
assert cognito.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test Cognito Session
|
||||
@mock_cognitoidp
|
||||
def test_audited_account(self):
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito = CognitoIDP(audit_info)
|
||||
assert cognito.audited_account == AWS_ACCOUNT_NUMBER
|
||||
|
||||
@mock_cognitoidp
|
||||
def test_list_user_pools(self):
|
||||
user_pool_name_1 = "user_pool_test_1"
|
||||
user_pool_name_2 = "user_pool_test_2"
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito_client_eu_west_1 = client("cognito-idp", region_name="eu-west-1")
|
||||
cognito_client_us_east_1 = client("cognito-idp", region_name="us-east-1")
|
||||
cognito_client_eu_west_1.create_user_pool(PoolName=user_pool_name_1)
|
||||
cognito_client_us_east_1.create_user_pool(PoolName=user_pool_name_2)
|
||||
cognito = CognitoIDP(audit_info)
|
||||
assert len(cognito.user_pools) == 2
|
||||
for user_pool in cognito.user_pools.values():
|
||||
assert (
|
||||
user_pool.name == user_pool_name_1 or user_pool.name == user_pool_name_2
|
||||
)
|
||||
assert user_pool.region == "eu-west-1" or user_pool.region == "us-east-1"
|
||||
|
||||
@mock_cognitoidp
|
||||
def test_describe_user_pools(self):
|
||||
user_pool_name_1 = "user_pool_test_1"
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito_client_eu_west_1 = client("cognito-idp", region_name="eu-west-1")
|
||||
user_pool_id = cognito_client_eu_west_1.create_user_pool(
|
||||
PoolName=user_pool_name_1
|
||||
)["UserPool"]["Id"]
|
||||
cognito = CognitoIDP(audit_info)
|
||||
assert len(cognito.user_pools) == 1
|
||||
for user_pool in cognito.user_pools.values():
|
||||
assert user_pool.name == user_pool_name_1
|
||||
assert user_pool.region == "eu-west-1"
|
||||
assert user_pool.id == user_pool_id
|
||||
assert user_pool.password_policy is not None
|
||||
assert user_pool.deletion_protection is not None
|
||||
assert user_pool.advanced_security_mode is not None
|
||||
assert user_pool.tags is not None
|
||||
|
||||
@mock_cognitoidp
|
||||
def test_get_user_pool_mfa_config(self):
|
||||
user_pool_name_1 = "user_pool_test_1"
|
||||
audit_info = set_mocked_aws_audit_info(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
cognito_client_eu_west_1 = client("cognito-idp", region_name="eu-west-1")
|
||||
user_pool_id = cognito_client_eu_west_1.create_user_pool(
|
||||
PoolName=user_pool_name_1
|
||||
)["UserPool"]["Id"]
|
||||
cognito_client_eu_west_1.set_user_pool_mfa_config(
|
||||
UserPoolId=user_pool_id,
|
||||
SoftwareTokenMfaConfiguration={"Enabled": True},
|
||||
MfaConfiguration="ON",
|
||||
)
|
||||
cognito = CognitoIDP(audit_info)
|
||||
assert len(cognito.user_pools) == 1
|
||||
for user_pool in cognito.user_pools.values():
|
||||
assert user_pool.name == user_pool_name_1
|
||||
assert user_pool.region == "eu-west-1"
|
||||
assert user_pool.id == user_pool_id
|
||||
assert user_pool.mfa_config is not None
|
||||
assert user_pool.mfa_config.sms_authentication == {}
|
||||
assert user_pool.mfa_config.software_token_mfa_authentication == {
|
||||
"Enabled": True
|
||||
}
|
||||
assert user_pool.mfa_config.status == "ON"
|
||||
@@ -48,6 +48,10 @@ for page in get_parameters_by_path_paginator.paginate(
|
||||
logging.info("Updating subservices and the services not present in the original matrix")
|
||||
# macie2 --> macie
|
||||
regions_by_service["services"]["macie2"] = regions_by_service["services"]["macie"]
|
||||
# cognito --> cognito-idp
|
||||
regions_by_service["services"]["cognito"] = regions_by_service["services"][
|
||||
"cognito-idp"
|
||||
]
|
||||
# opensearch --> es
|
||||
regions_by_service["services"]["opensearch"] = regions_by_service["services"]["es"]
|
||||
# elbv2 --> elb
|
||||
|
||||
Reference in New Issue
Block a user