feat(aws): Added AWS role session name parameter (#3234)

Co-authored-by: Sergio Garcia <sergargar1@gmail.com>
This commit is contained in:
Fennerr
2024-01-08 13:49:13 +02:00
committed by GitHub
parent 9522d0c733
commit 558b7a54c7
9 changed files with 88 additions and 7 deletions

View File

@@ -23,6 +23,15 @@ prowler aws -R arn:aws:iam::<account_id>:role/<role_name>
prowler aws -T/--session-duration <seconds> -I/--external-id <external_id> -R arn:aws:iam::<account_id>:role/<role_name> prowler aws -T/--session-duration <seconds> -I/--external-id <external_id> -R arn:aws:iam::<account_id>:role/<role_name>
``` ```
## Custom Role Session Name
Prowler can use your custom Role Session name with:
```console
prowler aws --role-session-name <role_session_name>
```
> It defaults to `ProwlerAssessmentSession`
## STS Endpoint Region ## STS Endpoint Region
If you are using Prowler in AWS regions that are not enabled by default you need to use the argument `--sts-endpoint-region` to point the AWS STS API calls `assume-role` and `get-caller-identity` to the non-default region, e.g.: `prowler aws --sts-endpoint-region eu-south-2`. If you are using Prowler in AWS regions that are not enabled by default you need to use the argument `--sts-endpoint-region` to point the AWS STS API calls `assume-role` and `get-caller-identity` to the non-default region, e.g.: `prowler aws --sts-endpoint-region eu-south-2`.

View File

@@ -113,9 +113,15 @@ def assume_role(
sts_endpoint_region: str = None, sts_endpoint_region: str = None,
) -> dict: ) -> dict:
try: try:
role_session_name = (
assumed_role_info.role_session_name
if assumed_role_info.role_session_name
else "ProwlerAssessmentSession"
)
assume_role_arguments = { assume_role_arguments = {
"RoleArn": assumed_role_info.role_arn, "RoleArn": assumed_role_info.role_arn,
"RoleSessionName": "ProwlerAsessmentSession", "RoleSessionName": role_session_name,
"DurationSeconds": assumed_role_info.session_duration, "DurationSeconds": assumed_role_info.session_duration,
} }

View File

@@ -1,5 +1,5 @@
from argparse import ArgumentTypeError, Namespace from argparse import ArgumentTypeError, Namespace
from re import search from re import fullmatch, search
from prowler.providers.aws.aws_provider import get_aws_available_regions from prowler.providers.aws.aws_provider import get_aws_available_regions
from prowler.providers.aws.lib.arn.arn import arn_type from prowler.providers.aws.lib.arn.arn import arn_type
@@ -27,6 +27,13 @@ def init_parser(self):
help="ARN of the role to be assumed", help="ARN of the role to be assumed",
# Pending ARN validation # Pending ARN validation
) )
aws_auth_subparser.add_argument(
"--role-session-name",
nargs="?",
default="ProwlerAssessmentSession",
help="An identifier for the assumed role session. Defaults to ProwlerAssessmentSession",
type=validate_role_session_name,
)
aws_auth_subparser.add_argument( aws_auth_subparser.add_argument(
"--sts-endpoint-region", "--sts-endpoint-region",
nargs="?", nargs="?",
@@ -203,3 +210,16 @@ def validate_bucket(bucket_name):
raise ArgumentTypeError( raise ArgumentTypeError(
"Bucket name must be valid (https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)" "Bucket name must be valid (https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)"
) )
def validate_role_session_name(session_name):
"""
validates that the role session name is valid
Documentation: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
"""
if fullmatch("[\w+=,.@-]{2,64}", session_name):
return session_name
else:
raise ArgumentTypeError(
"Role Session Name must be 2-64 characters long and consist only of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-"
)

View File

@@ -30,6 +30,7 @@ current_audit_info = AWS_Audit_Info(
session_duration=None, session_duration=None,
external_id=None, external_id=None,
mfa_enabled=None, mfa_enabled=None,
role_session_name=None,
), ),
mfa_enabled=None, mfa_enabled=None,
audit_resources=None, audit_resources=None,

View File

@@ -20,6 +20,7 @@ class AWS_Assume_Role:
session_duration: int session_duration: int
external_id: str external_id: str
mfa_enabled: bool mfa_enabled: bool
role_session_name: str
@dataclass @dataclass

View File

@@ -85,6 +85,7 @@ Azure Identity Type: {Fore.YELLOW}[{audit_info.identity.identity_type}]{Style.RE
current_audit_info.assumed_role_info.role_arn = input_role current_audit_info.assumed_role_info.role_arn = input_role
input_session_duration = arguments.get("session_duration") input_session_duration = arguments.get("session_duration")
input_external_id = arguments.get("external_id") input_external_id = arguments.get("external_id")
input_role_session_name = arguments.get("role_session_name")
# STS Endpoint Region # STS Endpoint Region
sts_endpoint_region = arguments.get("sts_endpoint_region") sts_endpoint_region = arguments.get("sts_endpoint_region")
@@ -153,6 +154,9 @@ Azure Identity Type: {Fore.YELLOW}[{audit_info.identity.identity_type}]{Style.RE
) )
current_audit_info.assumed_role_info.external_id = input_external_id current_audit_info.assumed_role_info.external_id = input_external_id
current_audit_info.assumed_role_info.mfa_enabled = input_mfa current_audit_info.assumed_role_info.mfa_enabled = input_mfa
current_audit_info.assumed_role_info.role_session_name = (
input_role_session_name
)
# Check if role arn is valid # Check if role arn is valid
try: try:

View File

@@ -5,7 +5,10 @@ import pytest
from mock import patch from mock import patch
from prowler.lib.cli.parser import ProwlerArgumentParser from prowler.lib.cli.parser import ProwlerArgumentParser
from prowler.providers.aws.lib.arguments.arguments import validate_bucket from prowler.providers.aws.lib.arguments.arguments import (
validate_bucket,
validate_role_session_name,
)
from prowler.providers.azure.lib.arguments.arguments import validate_azure_region from prowler.providers.azure.lib.arguments.arguments import validate_azure_region
prowler_command = "prowler" prowler_command = "prowler"
@@ -1012,6 +1015,13 @@ class Test_Parser:
parsed = self.parser.parse(command) parsed = self.parser.parse(command)
assert parsed.sts_endpoint_region == sts_endpoint_region assert parsed.sts_endpoint_region == sts_endpoint_region
def test_aws_parser_role_session_name(self):
argument = "--role-session-name"
role_session_name = "ProwlerAssessmentSession"
command = [prowler_command, argument, role_session_name]
parsed = self.parser.parse(command)
assert parsed.role_session_name == role_session_name
def test_parser_azure_auth_sp(self): def test_parser_azure_auth_sp(self):
argument = "--sp-env-auth" argument = "--sp-env-auth"
command = [prowler_command, "azure", argument] command = [prowler_command, "azure", argument]
@@ -1164,3 +1174,25 @@ class Test_Parser:
valid_bucket_names = ["bucket-name" "test" "test-test-test"] valid_bucket_names = ["bucket-name" "test" "test-test-test"]
for bucket_name in valid_bucket_names: for bucket_name in valid_bucket_names:
assert validate_bucket(bucket_name) == bucket_name assert validate_bucket(bucket_name) == bucket_name
def test_validate_role_session_name_invalid_role_names(self):
bad_role_names = [
"role name",
"adasD*",
"test#",
"role-name?",
]
for role_name in bad_role_names:
with pytest.raises(ArgumentTypeError) as argument_error:
validate_role_session_name(role_name)
assert argument_error.type == ArgumentTypeError
assert (
argument_error.value.args[0]
== "Role Session Name must be 2-64 characters long and consist only of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-"
)
def test_validate_role_session_name_valid_role_names(self):
valid_role_names = ["prowler-role" "test@" "test=test+test,."]
for role_name in valid_role_names:
assert validate_role_session_name(role_name) == role_name

View File

@@ -32,7 +32,7 @@ class Test_AWS_Provider:
@mock_iam @mock_iam
@mock_sts @mock_sts
def test_aws_provider_user_without_mfa(self): def test_aws_provider_user_without_mfa(self):
# sessionName = "ProwlerAsessmentSession" # sessionName = "ProwlerAssessmentSession"
# Boto 3 client to create our user # Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1) iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1)
# IAM user # IAM user
@@ -56,6 +56,7 @@ class Test_AWS_Provider:
session_duration=None, session_duration=None,
external_id=None, external_id=None,
mfa_enabled=False, mfa_enabled=False,
role_session_name="ProwlerAssessmentSession",
), ),
original_session=session, original_session=session,
) )
@@ -75,6 +76,7 @@ class Test_AWS_Provider:
session_duration=None, session_duration=None,
external_id=None, external_id=None,
mfa_enabled=False, mfa_enabled=False,
role_session_name="ProwlerAssessmentSession",
) )
@mock_iam @mock_iam
@@ -103,6 +105,7 @@ class Test_AWS_Provider:
session_duration=None, session_duration=None,
external_id=None, external_id=None,
mfa_enabled=False, mfa_enabled=False,
role_session_name="ProwlerAssessmentSession",
), ),
original_session=session, original_session=session,
profile_region=AWS_REGION_US_EAST_1, profile_region=AWS_REGION_US_EAST_1,
@@ -123,6 +126,7 @@ class Test_AWS_Provider:
session_duration=None, session_duration=None,
external_id=None, external_id=None,
mfa_enabled=False, mfa_enabled=False,
role_session_name="ProwlerAssessmentSession",
) )
@mock_iam @mock_iam
@@ -132,7 +136,7 @@ class Test_AWS_Provider:
role_name = "test-role" role_name = "test-role"
role_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/{role_name}" role_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/{role_name}"
session_duration_seconds = 900 session_duration_seconds = 900
sessionName = "ProwlerAsessmentSession" sessionName = "ProwlerAssessmentSession"
# Boto 3 client to create our user # Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1) iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1)
@@ -157,6 +161,7 @@ class Test_AWS_Provider:
session_duration=session_duration_seconds, session_duration=session_duration_seconds,
external_id=None, external_id=None,
mfa_enabled=True, mfa_enabled=True,
role_session_name="ProwlerAssessmentSession",
), ),
original_session=session, original_session=session,
profile_region=AWS_REGION_US_EAST_1, profile_region=AWS_REGION_US_EAST_1,
@@ -210,7 +215,7 @@ class Test_AWS_Provider:
role_name = "test-role" role_name = "test-role"
role_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/{role_name}" role_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/{role_name}"
session_duration_seconds = 900 session_duration_seconds = 900
sessionName = "ProwlerAsessmentSession" sessionName = "ProwlerAssessmentSession"
# Boto 3 client to create our user # Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1) iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1)
@@ -235,6 +240,7 @@ class Test_AWS_Provider:
session_duration=session_duration_seconds, session_duration=session_duration_seconds,
external_id=None, external_id=None,
mfa_enabled=False, mfa_enabled=False,
role_session_name="ProwlerAssessmentSession",
), ),
original_session=session, original_session=session,
profile_region=AWS_REGION_US_EAST_1, profile_region=AWS_REGION_US_EAST_1,
@@ -282,7 +288,7 @@ class Test_AWS_Provider:
session_duration_seconds = 900 session_duration_seconds = 900
AWS_REGION_US_EAST_1 = AWS_REGION_EU_WEST_1 AWS_REGION_US_EAST_1 = AWS_REGION_EU_WEST_1
sts_endpoint_region = AWS_REGION_US_EAST_1 sts_endpoint_region = AWS_REGION_US_EAST_1
sessionName = "ProwlerAsessmentSession" sessionName = "ProwlerAssessmentSession"
# Boto 3 client to create our user # Boto 3 client to create our user
iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1) iam_client = boto3.client("iam", region_name=AWS_REGION_US_EAST_1)
@@ -307,6 +313,7 @@ class Test_AWS_Provider:
session_duration=session_duration_seconds, session_duration=session_duration_seconds,
external_id=None, external_id=None,
mfa_enabled=False, mfa_enabled=False,
role_session_name="ProwlerAssessmentSession",
), ),
original_session=session, original_session=session,
profile_region=AWS_REGION_US_EAST_1, profile_region=AWS_REGION_US_EAST_1,

View File

@@ -116,6 +116,7 @@ class Test_Set_Audit_Info:
session_duration=None, session_duration=None,
external_id=None, external_id=None,
mfa_enabled=None, mfa_enabled=None,
role_session_name="ProwlerAssessmentSession",
), ),
audited_regions=["eu-west-2", "eu-west-1"], audited_regions=["eu-west-2", "eu-west-1"],
organizations_metadata=None, organizations_metadata=None,