test(aws_provider): Role and User MFA (#2486)

This commit is contained in:
Pepe Fagoaga
2023-07-18 09:36:37 +02:00
committed by GitHub
parent 65a737bb58
commit 28ea37f367
6 changed files with 271 additions and 96 deletions

View File

@@ -14,20 +14,17 @@ from prowler.providers.aws.aws_provider import (
from prowler.providers.aws.lib.audit_info.models import AWS_Assume_Role, AWS_Audit_Info
ACCOUNT_ID = 123456789012
AWS_REGION = "us-east-1"
class Test_AWS_Provider:
@mock_iam
@mock_sts
def test_assume_role_without_mfa(self):
# Variables
role_name = "test-role"
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/{role_name}"
session_duration_seconds = 900
def test_aws_provider_user_without_mfa(self):
audited_regions = ["eu-west-1"]
sessionName = "ProwlerAsessmentSession"
# sessionName = "ProwlerAsessmentSession"
# Boto 3 client to create our user
iam_client = boto3.client("iam", region_name="us-east-1")
iam_client = boto3.client("iam", region_name=AWS_REGION)
# IAM user
iam_user = iam_client.create_user(UserName="test-user")["User"]
access_key = iam_client.create_access_key(UserName=iam_user["UserName"])[
@@ -39,7 +36,7 @@ class Test_AWS_Provider:
session = boto3.session.Session(
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
region_name="us-east-1",
region_name=AWS_REGION,
)
# Fulfil the input session object for Prowler
@@ -56,8 +53,8 @@ class Test_AWS_Provider:
profile_region=None,
credentials=None,
assumed_role_info=AWS_Assume_Role(
role_arn=role_arn,
session_duration=session_duration_seconds,
role_arn=None,
session_duration=None,
external_id=None,
mfa_enabled=False,
),
@@ -68,47 +65,25 @@ class Test_AWS_Provider:
)
# Call assume_role
aws_provider = AWS_Provider(audit_info)
assume_role_response = assume_role(
aws_provider.aws_session, aws_provider.role_info
)
# Recover credentials for the assume role operation
credentials = assume_role_response["Credentials"]
# Test the response
# SessionToken
credentials["SessionToken"].should.have.length_of(356)
credentials["SessionToken"].startswith("FQoGZXIvYXdzE")
# AccessKeyId
credentials["AccessKeyId"].should.have.length_of(20)
credentials["AccessKeyId"].startswith("ASIA")
# SecretAccessKey
credentials["SecretAccessKey"].should.have.length_of(40)
# Assumed Role
assume_role_response["AssumedRoleUser"]["Arn"].should.equal(
f"arn:aws:sts::{ACCOUNT_ID}:assumed-role/{role_name}/{sessionName}"
)
# AssumedRoleUser
assert assume_role_response["AssumedRoleUser"]["AssumedRoleId"].startswith(
"AROA"
)
assert assume_role_response["AssumedRoleUser"]["AssumedRoleId"].endswith(
":" + sessionName
)
assume_role_response["AssumedRoleUser"]["AssumedRoleId"].should.have.length_of(
21 + 1 + len(sessionName)
)
with patch(
"prowler.providers.aws.aws_provider.input_role_mfa_token_and_code",
return_value=(f"arn:aws:iam::{ACCOUNT_ID}:mfa/test-role-mfa", "111111"),
):
aws_provider = AWS_Provider(audit_info)
assert aws_provider.aws_session.region_name is None
assert aws_provider.role_info == AWS_Assume_Role(
role_arn=None,
session_duration=None,
external_id=None,
mfa_enabled=False,
)
@mock_iam
@mock_sts
def test_assume_role_with_mfa(self):
# Variables
role_name = "test-role"
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/{role_name}"
session_duration_seconds = 900
audited_regions = ["eu-west-1"]
sessionName = "ProwlerAsessmentSession"
def test_aws_provider_user_with_mfa(self):
audited_regions = "eu-west-1"
# Boto 3 client to create our user
iam_client = boto3.client("iam", region_name="us-east-1")
iam_client = boto3.client("iam", region_name=AWS_REGION)
# IAM user
iam_user = iam_client.create_user(UserName="test-user")["User"]
access_key = iam_client.create_access_key(UserName=iam_user["UserName"])[
@@ -120,7 +95,71 @@ class Test_AWS_Provider:
session = boto3.session.Session(
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
region_name="us-east-1",
region_name=AWS_REGION,
)
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
session_config=None,
original_session=session,
audit_session=None,
audited_account=None,
audited_account_arn=None,
audited_partition=None,
audited_identity_arn=None,
audited_user_id=None,
profile=None,
profile_region=AWS_REGION,
credentials=None,
assumed_role_info=AWS_Assume_Role(
role_arn=None,
session_duration=None,
external_id=None,
mfa_enabled=False,
),
audited_regions=audited_regions,
organizations_metadata=None,
audit_resources=None,
mfa_enabled=True,
)
# # Call assume_role
with patch(
"prowler.providers.aws.aws_provider.input_role_mfa_token_and_code",
return_value=(f"arn:aws:iam::{ACCOUNT_ID}:mfa/test-role-mfa", "111111"),
):
aws_provider = AWS_Provider(audit_info)
assert aws_provider.aws_session.region_name is None
assert aws_provider.role_info == AWS_Assume_Role(
role_arn=None,
session_duration=None,
external_id=None,
mfa_enabled=False,
)
@mock_iam
@mock_sts
def test_aws_provider_assume_role_with_mfa(self):
# Variables
role_name = "test-role"
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/{role_name}"
session_duration_seconds = 900
audited_regions = ["eu-west-1"]
sessionName = "ProwlerAsessmentSession"
# Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=AWS_REGION)
# IAM user
iam_user = iam_client.create_user(UserName="test-user")["User"]
access_key = iam_client.create_access_key(UserName=iam_user["UserName"])[
"AccessKey"
]
access_key_id = access_key["AccessKeyId"]
secret_access_key = access_key["SecretAccessKey"]
# New Boto3 session with the previously create user
session = boto3.session.Session(
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
region_name=AWS_REGION,
)
# Fulfil the input session object for Prowler
@@ -186,17 +225,15 @@ class Test_AWS_Provider:
@mock_iam
@mock_sts
def test_assume_role_with_sts_endpoint_region(self):
def test_aws_provider_assume_role_without_mfa(self):
# Variables
role_name = "test-role"
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/{role_name}"
session_duration_seconds = 900
aws_region = "eu-west-1"
sts_endpoint_region = aws_region
audited_regions = [aws_region]
audited_regions = "eu-west-1"
sessionName = "ProwlerAsessmentSession"
# Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=aws_region)
iam_client = boto3.client("iam", region_name=AWS_REGION)
# IAM user
iam_user = iam_client.create_user(UserName="test-user")["User"]
access_key = iam_client.create_access_key(UserName=iam_user["UserName"])[
@@ -208,7 +245,90 @@ class Test_AWS_Provider:
session = boto3.session.Session(
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
region_name=aws_region,
region_name=AWS_REGION,
)
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
session_config=None,
original_session=session,
audit_session=None,
audited_account=None,
audited_account_arn=None,
audited_partition=None,
audited_identity_arn=None,
audited_user_id=None,
profile=None,
profile_region=None,
credentials=None,
assumed_role_info=AWS_Assume_Role(
role_arn=role_arn,
session_duration=session_duration_seconds,
external_id=None,
mfa_enabled=False,
),
audited_regions=audited_regions,
organizations_metadata=None,
audit_resources=None,
mfa_enabled=False,
)
# Call assume_role
aws_provider = AWS_Provider(audit_info)
assume_role_response = assume_role(
aws_provider.aws_session, aws_provider.role_info
)
# Recover credentials for the assume role operation
credentials = assume_role_response["Credentials"]
# Test the response
# SessionToken
credentials["SessionToken"].should.have.length_of(356)
credentials["SessionToken"].startswith("FQoGZXIvYXdzE")
# AccessKeyId
credentials["AccessKeyId"].should.have.length_of(20)
credentials["AccessKeyId"].startswith("ASIA")
# SecretAccessKey
credentials["SecretAccessKey"].should.have.length_of(40)
# Assumed Role
assume_role_response["AssumedRoleUser"]["Arn"].should.equal(
f"arn:aws:sts::{ACCOUNT_ID}:assumed-role/{role_name}/{sessionName}"
)
# AssumedRoleUser
assert assume_role_response["AssumedRoleUser"]["AssumedRoleId"].startswith(
"AROA"
)
assert assume_role_response["AssumedRoleUser"]["AssumedRoleId"].endswith(
":" + sessionName
)
assume_role_response["AssumedRoleUser"]["AssumedRoleId"].should.have.length_of(
21 + 1 + len(sessionName)
)
@mock_iam
@mock_sts
def test_assume_role_with_sts_endpoint_region(self):
# Variables
role_name = "test-role"
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/{role_name}"
session_duration_seconds = 900
aws_region = "eu-west-1"
sts_endpoint_region = aws_region
audited_regions = [aws_region]
sessionName = "ProwlerAsessmentSession"
# Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=AWS_REGION)
# IAM user
iam_user = iam_client.create_user(UserName="test-user")["User"]
access_key = iam_client.create_access_key(UserName=iam_user["UserName"])[
"AccessKey"
]
access_key_id = access_key["AccessKeyId"]
secret_access_key = access_key["SecretAccessKey"]
# New Boto3 session with the previously create user
session = boto3.session.Session(
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
region_name=AWS_REGION,
)
# Fulfil the input session object for Prowler
@@ -270,9 +390,9 @@ class Test_AWS_Provider:
def test_generate_regional_clients(self):
# New Boto3 session with the previously create user
session = boto3.session.Session(
region_name="us-east-1",
region_name=AWS_REGION,
)
audited_regions = ["eu-west-1", "us-east-1"]
audited_regions = ["eu-west-1", AWS_REGION]
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
session_config=None,
@@ -301,10 +421,10 @@ class Test_AWS_Provider:
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",
region_name=AWS_REGION,
)
audited_regions = ["eu-west-1", "us-east-1"]
profile_region = "us-east-1"
audited_regions = ["eu-west-1", AWS_REGION]
profile_region = AWS_REGION
# Fulfil the input session object for Prowler
audit_info = AWS_Audit_Info(
session_config=None,
@@ -333,7 +453,7 @@ class Test_AWS_Provider:
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",
region_name=AWS_REGION,
)
audited_regions = ["cn-northwest-1", "cn-north-1"]
# Fulfil the input session object for Prowler

View File

@@ -1,5 +1,6 @@
import boto3
import botocore
import pytest
import sure # noqa
from boto3 import session
from mock import patch
@@ -119,37 +120,6 @@ class Test_Set_Audit_Info:
return audit_info
@patch(
"prowler.providers.common.audit_info.validate_aws_credentials",
new=mock_validate_credentials,
)
@patch(
"prowler.providers.common.audit_info.print_aws_credentials",
new=mock_print_audit_credentials,
)
def test_set_audit_info_aws(self):
with patch(
"prowler.providers.common.audit_info.current_audit_info",
new=self.set_mocked_audit_info(),
):
provider = "aws"
arguments = {
"profile": None,
"role": None,
"session_duration": None,
"external_id": None,
"regions": None,
"organizations_role": None,
"subscriptions": None,
"az_cli_auth": None,
"sp_env_auth": None,
"browser_auth": None,
"managed_entity_auth": None,
}
audit_info = set_provider_audit_info(provider, arguments)
assert isinstance(audit_info, AWS_Audit_Info)
@patch(
"prowler.providers.common.audit_info.azure_audit_info",
new=mock_azure_audit_info,
@@ -245,3 +215,89 @@ class Test_Set_Audit_Info:
assert instance_id in str(
get_tagged_resources(["MY_TAG1=MY_VALUE1"], mock_audit_info)
)
@patch(
"prowler.providers.common.audit_info.validate_aws_credentials",
new=mock_validate_credentials,
)
@patch(
"prowler.providers.common.audit_info.print_aws_credentials",
new=mock_print_audit_credentials,
)
def test_set_audit_info_aws(self):
with patch(
"prowler.providers.common.audit_info.current_audit_info",
new=self.set_mocked_audit_info(),
):
provider = "aws"
arguments = {
"profile": None,
"role": None,
"session_duration": None,
"external_id": None,
"regions": None,
"organizations_role": None,
}
audit_info = set_provider_audit_info(provider, arguments)
assert isinstance(audit_info, AWS_Audit_Info)
def test_set_audit_info_aws_bad_session_duration(self):
with patch(
"prowler.providers.common.audit_info.current_audit_info",
new=self.set_mocked_audit_info(),
):
provider = "aws"
arguments = {
"profile": None,
"role": None,
"session_duration": 100,
"external_id": None,
"regions": None,
"organizations_role": None,
}
with pytest.raises(SystemExit) as exception:
_ = set_provider_audit_info(provider, arguments)
# assert exception == "Value for -T option must be between 900 and 43200"
assert isinstance(exception, pytest.ExceptionInfo)
def test_set_audit_info_aws_session_duration_without_role(self):
with patch(
"prowler.providers.common.audit_info.current_audit_info",
new=self.set_mocked_audit_info(),
):
provider = "aws"
arguments = {
"profile": None,
"role": None,
"session_duration": 1000,
"external_id": None,
"regions": None,
"organizations_role": None,
}
with pytest.raises(SystemExit) as exception:
_ = set_provider_audit_info(provider, arguments)
# assert exception == "To use -I/-T options -R option is needed"
assert isinstance(exception, pytest.ExceptionInfo)
def test_set_audit_info_external_id_without_role(self):
with patch(
"prowler.providers.common.audit_info.current_audit_info",
new=self.set_mocked_audit_info(),
):
provider = "aws"
arguments = {
"profile": None,
"role": None,
"session_duration": 3600,
"external_id": "test-external-id",
"regions": None,
"organizations_role": None,
}
with pytest.raises(SystemExit) as exception:
_ = set_provider_audit_info(provider, arguments)
# assert exception == "To use -I/-T options -R option is needed"
assert isinstance(exception, pytest.ExceptionInfo)