mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-04 02:04:06 +00:00
fix(aws): configurable boto3 timeouts, 10s connect default (#12774)
This commit is contained in:
@@ -1152,6 +1152,35 @@ class Test_Parser:
|
||||
parsed = self.parser.parse(command)
|
||||
assert parsed.aws_retries_max_attempts == int(max_retries)
|
||||
|
||||
def test_aws_parser_retries_max_attempts_zero(self):
|
||||
command = [prowler_command, "--aws-retries-max-attempts", "0"]
|
||||
parsed = self.parser.parse(command)
|
||||
assert parsed.aws_retries_max_attempts == 0
|
||||
|
||||
def test_aws_parser_timeouts_default_to_none(self):
|
||||
parsed = self.parser.parse([prowler_command])
|
||||
assert parsed.aws_connect_timeout is None
|
||||
assert parsed.aws_read_timeout is None
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"argument, attribute",
|
||||
[
|
||||
("--aws-connect-timeout", "aws_connect_timeout"),
|
||||
("--aws-read-timeout", "aws_read_timeout"),
|
||||
],
|
||||
)
|
||||
def test_aws_parser_timeouts(self, argument, attribute):
|
||||
timeout = "5"
|
||||
command = [prowler_command, argument, timeout]
|
||||
parsed = self.parser.parse(command)
|
||||
assert getattr(parsed, attribute) == int(timeout)
|
||||
|
||||
@pytest.mark.parametrize("value", ["0", "-1", "abc"])
|
||||
def test_aws_parser_connect_timeout_rejects_non_positive(self, value):
|
||||
command = [prowler_command, "--aws-connect-timeout", value]
|
||||
with pytest.raises(SystemExit):
|
||||
self.parser.parse(command)
|
||||
|
||||
def test_aws_parser_scan_unused_services(self):
|
||||
argument = "--scan-unused-services"
|
||||
command = [prowler_command, argument]
|
||||
|
||||
@@ -24,19 +24,24 @@ from prowler.providers.aws.aws_provider import (
|
||||
)
|
||||
from prowler.providers.aws.config import (
|
||||
AWS_STS_GLOBAL_ENDPOINT_REGION,
|
||||
BOTO3_CONNECT_TIMEOUT,
|
||||
BOTO3_READ_TIMEOUT,
|
||||
BOTO3_USER_AGENT_EXTRA,
|
||||
ROLE_SESSION_NAME,
|
||||
get_boto3_timeout_from_env,
|
||||
get_default_session_config,
|
||||
)
|
||||
from prowler.providers.aws.exceptions.exceptions import (
|
||||
AWSArgumentTypeValidationError,
|
||||
AWSIAMRoleARNInvalidResourceTypeError,
|
||||
AWSInvalidBoto3TimeoutError,
|
||||
AWSInvalidPartitionError,
|
||||
AWSInvalidProviderIdError,
|
||||
AWSNoCredentialsError,
|
||||
)
|
||||
from prowler.providers.aws.lib.arn.models import ARN
|
||||
from prowler.providers.aws.lib.mutelist.mutelist import AWSMutelist
|
||||
from prowler.providers.aws.lib.session.aws_set_up_session import AwsSetUpSession
|
||||
from prowler.providers.aws.models import (
|
||||
AWSAssumeRoleInfo,
|
||||
AWSCallerIdentity,
|
||||
@@ -2735,6 +2740,8 @@ aws:
|
||||
|
||||
assert session_config.user_agent_extra == BOTO3_USER_AGENT_EXTRA
|
||||
assert session_config.retries == {"max_attempts": 3, "mode": "standard"}
|
||||
assert session_config.connect_timeout == BOTO3_CONNECT_TIMEOUT
|
||||
assert session_config.read_timeout == BOTO3_READ_TIMEOUT
|
||||
|
||||
@mock_aws
|
||||
def test_set_session_config_10_max_attempts(self):
|
||||
@@ -2743,12 +2750,93 @@ aws:
|
||||
|
||||
assert session_config.user_agent_extra == BOTO3_USER_AGENT_EXTRA
|
||||
assert session_config.retries == {"max_attempts": 10, "mode": "standard"}
|
||||
assert session_config.connect_timeout == BOTO3_CONNECT_TIMEOUT
|
||||
assert session_config.read_timeout == BOTO3_READ_TIMEOUT
|
||||
|
||||
def test_set_session_config_0_max_attempts_disables_retries(self):
|
||||
session_config = AwsProvider.set_session_config(0)
|
||||
|
||||
assert session_config.retries == {"max_attempts": 0, "mode": "standard"}
|
||||
|
||||
@mock_aws
|
||||
def test_aws_provider_0_max_attempts_reaches_clients(self):
|
||||
aws_provider = AwsProvider(retries_max_attempts=0)
|
||||
client = aws_provider.session.current_session.client(
|
||||
"ec2", region_name=AWS_REGION_US_EAST_1
|
||||
)
|
||||
|
||||
# botocore rewrites max_attempts into total_max_attempts (retries + 1)
|
||||
assert client.meta.config.retries["total_max_attempts"] == 1
|
||||
|
||||
def test_set_session_config_timeouts(self):
|
||||
session_config = AwsProvider.set_session_config(
|
||||
None, connect_timeout=2, read_timeout=15
|
||||
)
|
||||
|
||||
assert session_config.retries == {"max_attempts": 3, "mode": "standard"}
|
||||
assert session_config.connect_timeout == 2
|
||||
assert session_config.read_timeout == 15
|
||||
|
||||
@mock_aws
|
||||
def test_aws_provider_timeouts_reach_session_config(self):
|
||||
aws_provider = AwsProvider(connect_timeout=2, read_timeout=15)
|
||||
|
||||
assert aws_provider.session.session_config.connect_timeout == 2
|
||||
assert aws_provider.session.session_config.read_timeout == 15
|
||||
|
||||
@mock_aws
|
||||
def test_aws_set_up_session_forwards_timeouts(self):
|
||||
aws_session = AwsSetUpSession(
|
||||
aws_access_key_id="testing",
|
||||
aws_secret_access_key="testing",
|
||||
connect_timeout=2,
|
||||
read_timeout=15,
|
||||
)
|
||||
|
||||
assert aws_session._session.session_config.connect_timeout == 2
|
||||
assert aws_session._session.session_config.read_timeout == 15
|
||||
|
||||
def test_get_default_session_config(self):
|
||||
config = get_default_session_config()
|
||||
|
||||
assert config.user_agent_extra == BOTO3_USER_AGENT_EXTRA
|
||||
assert config.retries == {"max_attempts": 3, "mode": "standard"}
|
||||
assert config.connect_timeout == BOTO3_CONNECT_TIMEOUT
|
||||
assert config.read_timeout == BOTO3_READ_TIMEOUT
|
||||
|
||||
def test_get_default_session_config_timeouts_from_env(self):
|
||||
with mock.patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": "3",
|
||||
"PROWLER_AWS_BOTO3_READ_TIMEOUT": "20",
|
||||
},
|
||||
):
|
||||
config = get_default_session_config()
|
||||
|
||||
assert config.connect_timeout == 3
|
||||
assert config.read_timeout == 20
|
||||
|
||||
def test_set_session_config_argument_overrides_env_timeouts(self):
|
||||
with mock.patch.dict(os.environ, {"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": "3"}):
|
||||
config = AwsProvider.set_session_config(None, connect_timeout=7)
|
||||
|
||||
assert config.connect_timeout == 7
|
||||
|
||||
@pytest.mark.parametrize("raw", ["0", "-5", "ten", "1.5"])
|
||||
def test_get_boto3_timeout_from_env_rejects_non_positive_integers(self, raw):
|
||||
with mock.patch.dict(os.environ, {"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": raw}):
|
||||
with raises(
|
||||
AWSInvalidBoto3TimeoutError, match="PROWLER_AWS_BOTO3_CONNECT_TIMEOUT"
|
||||
):
|
||||
get_boto3_timeout_from_env("PROWLER_AWS_BOTO3_CONNECT_TIMEOUT", 10)
|
||||
|
||||
def test_get_boto3_timeout_from_env_blank_falls_back_to_default(self):
|
||||
with mock.patch.dict(os.environ, {"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": " "}):
|
||||
assert (
|
||||
get_boto3_timeout_from_env("PROWLER_AWS_BOTO3_CONNECT_TIMEOUT", 10)
|
||||
== 10
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
@patch(
|
||||
|
||||
Reference in New Issue
Block a user