mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(aws): Added AWS role session name parameter (#3234)
Co-authored-by: Sergio Garcia <sergargar1@gmail.com>
This commit is contained in:
@@ -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`.
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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: =,.@-"
|
||||||
|
)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user