Techdebt: MyPy IAM (#6066)

This commit is contained in:
Bert Blommers 2023-03-14 18:52:07 -01:00 committed by GitHub
parent f1fcbfaa00
commit fe8d30ae63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1047 additions and 803 deletions

View File

@ -108,7 +108,7 @@ class ConfigQueryModel:
backend_region: Optional[str] = None, backend_region: Optional[str] = None,
resource_region: Optional[str] = None, resource_region: Optional[str] = None,
aggregator: Optional[Dict[str, Any]] = None, aggregator: Optional[Dict[str, Any]] = None,
) -> Tuple[List[Dict[str, Any]], str]: ) -> Tuple[List[Dict[str, Any]], Optional[str]]:
"""For AWS Config. This will list all of the resources of the given type and optional resource name and region. """For AWS Config. This will list all of the resources of the given type and optional resource name and region.
This supports both aggregated and non-aggregated listing. The following notes the difference: This supports both aggregated and non-aggregated listing. The following notes the difference:
@ -165,7 +165,7 @@ class ConfigQueryModel:
resource_name: Optional[str] = None, resource_name: Optional[str] = None,
backend_region: Optional[str] = None, backend_region: Optional[str] = None,
resource_region: Optional[str] = None, resource_region: Optional[str] = None,
) -> Dict[str, Any]: ) -> Optional[Dict[str, Any]]:
"""For AWS Config. This will query the backend for the specific resource type configuration. """For AWS Config. This will query the backend for the specific resource type configuration.
This supports both aggregated, and non-aggregated fetching -- for batched fetching -- the Config batching requests This supports both aggregated, and non-aggregated fetching -- for batched fetching -- the Config batching requests
@ -194,7 +194,7 @@ class ConfigQueryModel:
raise NotImplementedError() raise NotImplementedError()
class CloudWatchMetricProvider(object): class CloudWatchMetricProvider:
@staticmethod @staticmethod
@abstractmethod @abstractmethod
def get_cloudwatch_metrics(account_id: str) -> Any: # type: ignore[misc] def get_cloudwatch_metrics(account_id: str) -> Any: # type: ignore[misc]

View File

@ -154,7 +154,9 @@ def iso_8601_datetime_with_nanoseconds(value: datetime.datetime) -> str:
return value.strftime("%Y-%m-%dT%H:%M:%S.%f000Z") return value.strftime("%Y-%m-%dT%H:%M:%S.%f000Z")
def iso_8601_datetime_without_milliseconds(value: datetime.datetime) -> Optional[str]: def iso_8601_datetime_without_milliseconds(
value: Optional[datetime.datetime],
) -> Optional[str]:
return value.strftime("%Y-%m-%dT%H:%M:%SZ") if value else None return value.strftime("%Y-%m-%dT%H:%M:%SZ") if value else None

View File

@ -17,6 +17,7 @@ import logging
import re import re
from abc import abstractmethod, ABCMeta from abc import abstractmethod, ABCMeta
from enum import Enum from enum import Enum
from typing import Any, Dict, Optional, Match, List, Union
from botocore.auth import SigV4Auth, S3SigV4Auth from botocore.auth import SigV4Auth, S3SigV4Auth
from botocore.awsrequest import AWSRequest from botocore.awsrequest import AWSRequest
@ -39,12 +40,14 @@ from moto.s3.exceptions import (
S3SignatureDoesNotMatchError, S3SignatureDoesNotMatchError,
) )
from moto.sts.models import sts_backends from moto.sts.models import sts_backends
from .models import iam_backends, Policy from .models import iam_backends, Policy, IAMBackend
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def create_access_key(account_id, access_key_id, headers): def create_access_key(
account_id: str, access_key_id: str, headers: Dict[str, str]
) -> Union["IAMUserAccessKey", "AssumedRoleAccessKey"]:
if access_key_id.startswith("AKIA") or "X-Amz-Security-Token" not in headers: if access_key_id.startswith("AKIA") or "X-Amz-Security-Token" not in headers:
return IAMUserAccessKey(account_id, access_key_id, headers) return IAMUserAccessKey(account_id, access_key_id, headers)
else: else:
@ -53,10 +56,10 @@ def create_access_key(account_id, access_key_id, headers):
class IAMUserAccessKey: class IAMUserAccessKey:
@property @property
def backend(self): def backend(self) -> IAMBackend:
return iam_backends[self.account_id]["global"] return iam_backends[self.account_id]["global"]
def __init__(self, account_id, access_key_id, headers): def __init__(self, account_id: str, access_key_id: str, headers: Dict[str, str]):
self.account_id = account_id self.account_id = account_id
iam_users = self.backend.list_users("/", None, None) iam_users = self.backend.list_users("/", None, None)
@ -72,13 +75,13 @@ class IAMUserAccessKey:
raise CreateAccessKeyFailure(reason="InvalidId") raise CreateAccessKeyFailure(reason="InvalidId")
@property @property
def arn(self): def arn(self) -> str:
return f"arn:aws:iam::{self.account_id}:user/{self._owner_user_name}" return f"arn:aws:iam::{self.account_id}:user/{self._owner_user_name}"
def create_credentials(self): def create_credentials(self) -> Credentials:
return Credentials(self._access_key_id, self._secret_access_key) return Credentials(self._access_key_id, self._secret_access_key)
def collect_policies(self): def collect_policies(self) -> List[Dict[str, str]]:
user_policies = [] user_policies = []
inline_policy_names = self.backend.list_user_policies(self._owner_user_name) inline_policy_names = self.backend.list_user_policies(self._owner_user_name)
@ -112,12 +115,12 @@ class IAMUserAccessKey:
return user_policies return user_policies
class AssumedRoleAccessKey(object): class AssumedRoleAccessKey:
@property @property
def backend(self): def backend(self) -> IAMBackend: # type: ignore[misc]
return iam_backends[self.account_id]["global"] return iam_backends[self.account_id]["global"]
def __init__(self, account_id, access_key_id, headers): def __init__(self, account_id: str, access_key_id: str, headers: Dict[str, str]):
self.account_id = account_id self.account_id = account_id
for assumed_role in sts_backends[account_id]["global"].assumed_roles: for assumed_role in sts_backends[account_id]["global"].assumed_roles:
if assumed_role.access_key_id == access_key_id: if assumed_role.access_key_id == access_key_id:
@ -132,15 +135,15 @@ class AssumedRoleAccessKey(object):
raise CreateAccessKeyFailure(reason="InvalidId") raise CreateAccessKeyFailure(reason="InvalidId")
@property @property
def arn(self): def arn(self) -> str:
return f"arn:aws:sts::{self.account_id}:assumed-role/{self._owner_role_name}/{self._session_name}" return f"arn:aws:sts::{self.account_id}:assumed-role/{self._owner_role_name}/{self._session_name}"
def create_credentials(self): def create_credentials(self) -> Credentials:
return Credentials( return Credentials(
self._access_key_id, self._secret_access_key, self._session_token self._access_key_id, self._secret_access_key, self._session_token
) )
def collect_policies(self): def collect_policies(self) -> List[str]:
role_policies = [] role_policies = []
inline_policy_names = self.backend.list_role_policies(self._owner_role_name) inline_policy_names = self.backend.list_role_policies(self._owner_role_name)
@ -153,19 +156,26 @@ class AssumedRoleAccessKey(object):
attached_policies, _ = self.backend.list_attached_role_policies( attached_policies, _ = self.backend.list_attached_role_policies(
self._owner_role_name self._owner_role_name
) )
role_policies += attached_policies role_policies += attached_policies # type: ignore[arg-type]
return role_policies return role_policies
class CreateAccessKeyFailure(Exception): class CreateAccessKeyFailure(Exception):
def __init__(self, reason, *args): def __init__(self, reason: str):
super().__init__(*args) super().__init__()
self.reason = reason self.reason = reason
class IAMRequestBase(object, metaclass=ABCMeta): class IAMRequestBase(object, metaclass=ABCMeta):
def __init__(self, account_id, method, path, data, headers): def __init__(
self,
account_id: str,
method: str,
path: str,
data: Dict[str, str],
headers: Dict[str, str],
):
log.debug( log.debug(
f"Creating {self.__class__.__name__} with method={method}, path={path}, data={data}, headers={headers}" f"Creating {self.__class__.__name__} with method={method}, path={path}, data={data}, headers={headers}"
) )
@ -198,7 +208,7 @@ class IAMRequestBase(object, metaclass=ABCMeta):
except CreateAccessKeyFailure as e: except CreateAccessKeyFailure as e:
self._raise_invalid_access_key(e.reason) self._raise_invalid_access_key(e.reason)
def check_signature(self): def check_signature(self) -> None:
original_signature = self._get_string_between( original_signature = self._get_string_between(
"Signature=", ",", self._headers["Authorization"] "Signature=", ",", self._headers["Authorization"]
) )
@ -206,11 +216,11 @@ class IAMRequestBase(object, metaclass=ABCMeta):
if original_signature != calculated_signature: if original_signature != calculated_signature:
self._raise_signature_does_not_match() self._raise_signature_does_not_match()
def check_action_permitted(self): def check_action_permitted(self) -> None:
if ( if (
self._action == "sts:GetCallerIdentity" self._action == "sts:GetCallerIdentity"
): # always allowed, even if there's an explicit Deny for it ): # always allowed, even if there's an explicit Deny for it
return True return
policies = self._access_key.collect_policies() policies = self._access_key.collect_policies()
permitted = False permitted = False
@ -226,30 +236,32 @@ class IAMRequestBase(object, metaclass=ABCMeta):
self._raise_access_denied() self._raise_access_denied()
@abstractmethod @abstractmethod
def _raise_signature_does_not_match(self): def _raise_signature_does_not_match(self) -> None:
raise NotImplementedError() raise NotImplementedError()
@abstractmethod @abstractmethod
def _raise_access_denied(self): def _raise_access_denied(self) -> None:
raise NotImplementedError() raise NotImplementedError()
@abstractmethod @abstractmethod
def _raise_invalid_access_key(self, reason): def _raise_invalid_access_key(self, reason: str) -> None:
raise NotImplementedError() raise NotImplementedError()
@abstractmethod @abstractmethod
def _create_auth(self, credentials): def _create_auth(self, credentials: Credentials) -> SigV4Auth: # type: ignore[misc]
raise NotImplementedError() raise NotImplementedError()
@staticmethod @staticmethod
def _create_headers_for_aws_request(signed_headers, original_headers): def _create_headers_for_aws_request(
signed_headers: List[str], original_headers: Dict[str, str]
) -> Dict[str, str]:
headers = {} headers = {}
for key, value in original_headers.items(): for key, value in original_headers.items():
if key.lower() in signed_headers: if key.lower() in signed_headers:
headers[key] = value headers[key] = value
return headers return headers
def _create_aws_request(self): def _create_aws_request(self) -> AWSRequest:
signed_headers = self._get_string_between( signed_headers = self._get_string_between(
"SignedHeaders=", ",", self._headers["Authorization"] "SignedHeaders=", ",", self._headers["Authorization"]
).split(";") ).split(";")
@ -261,7 +273,7 @@ class IAMRequestBase(object, metaclass=ABCMeta):
return request return request
def _calculate_signature(self): def _calculate_signature(self) -> str:
credentials = self._access_key.create_credentials() credentials = self._access_key.create_credentials()
auth = self._create_auth(credentials) auth = self._create_auth(credentials)
request = self._create_aws_request() request = self._create_aws_request()
@ -270,38 +282,40 @@ class IAMRequestBase(object, metaclass=ABCMeta):
return auth.signature(string_to_sign, request) return auth.signature(string_to_sign, request)
@staticmethod @staticmethod
def _get_string_between(first_separator, second_separator, string): def _get_string_between(
first_separator: str, second_separator: str, string: str
) -> str:
return string.partition(first_separator)[2].partition(second_separator)[0] return string.partition(first_separator)[2].partition(second_separator)[0]
class IAMRequest(IAMRequestBase): class IAMRequest(IAMRequestBase):
def _raise_signature_does_not_match(self): def _raise_signature_does_not_match(self) -> None:
if self._service == "ec2": if self._service == "ec2":
raise AuthFailureError() raise AuthFailureError()
else: else:
raise SignatureDoesNotMatchError() raise SignatureDoesNotMatchError()
def _raise_invalid_access_key(self, _): def _raise_invalid_access_key(self, _: str) -> None:
if self._service == "ec2": if self._service == "ec2":
raise AuthFailureError() raise AuthFailureError()
else: else:
raise InvalidClientTokenIdError() raise InvalidClientTokenIdError()
def _create_auth(self, credentials): def _create_auth(self, credentials: Any) -> SigV4Auth:
return SigV4Auth(credentials, self._service, self._region) return SigV4Auth(credentials, self._service, self._region)
def _raise_access_denied(self): def _raise_access_denied(self) -> None:
raise AccessDeniedError(user_arn=self._access_key.arn, action=self._action) raise AccessDeniedError(user_arn=self._access_key.arn, action=self._action)
class S3IAMRequest(IAMRequestBase): class S3IAMRequest(IAMRequestBase):
def _raise_signature_does_not_match(self): def _raise_signature_does_not_match(self) -> None:
if "BucketName" in self._data: if "BucketName" in self._data:
raise BucketSignatureDoesNotMatchError(bucket=self._data["BucketName"]) raise BucketSignatureDoesNotMatchError(bucket=self._data["BucketName"])
else: else:
raise S3SignatureDoesNotMatchError() raise S3SignatureDoesNotMatchError()
def _raise_invalid_access_key(self, reason): def _raise_invalid_access_key(self, reason: str) -> None:
if reason == "InvalidToken": if reason == "InvalidToken":
if "BucketName" in self._data: if "BucketName" in self._data:
raise BucketInvalidTokenError(bucket=self._data["BucketName"]) raise BucketInvalidTokenError(bucket=self._data["BucketName"])
@ -313,18 +327,18 @@ class S3IAMRequest(IAMRequestBase):
else: else:
raise S3InvalidAccessKeyIdError() raise S3InvalidAccessKeyIdError()
def _create_auth(self, credentials): def _create_auth(self, credentials: Any) -> S3SigV4Auth:
return S3SigV4Auth(credentials, self._service, self._region) return S3SigV4Auth(credentials, self._service, self._region)
def _raise_access_denied(self): def _raise_access_denied(self) -> None:
if "BucketName" in self._data: if "BucketName" in self._data:
raise BucketAccessDeniedError(bucket=self._data["BucketName"]) raise BucketAccessDeniedError(bucket=self._data["BucketName"])
else: else:
raise S3AccessDeniedError() raise S3AccessDeniedError()
class IAMPolicy(object): class IAMPolicy:
def __init__(self, policy): def __init__(self, policy: Any):
if isinstance(policy, Policy): if isinstance(policy, Policy):
default_version = next( default_version = next(
policy_version policy_version
@ -337,9 +351,11 @@ class IAMPolicy(object):
else: else:
policy_document = policy["policy_document"] policy_document = policy["policy_document"]
self._policy_json = json.loads(policy_document) self._policy_json = json.loads(policy_document) # type: ignore[arg-type]
def is_action_permitted(self, action, resource="*"): def is_action_permitted(
self, action: str, resource: str = "*"
) -> "PermissionResult":
permitted = False permitted = False
if isinstance(self._policy_json["Statement"], list): if isinstance(self._policy_json["Statement"], list):
for policy_statement in self._policy_json["Statement"]: for policy_statement in self._policy_json["Statement"]:
@ -361,11 +377,13 @@ class IAMPolicy(object):
return PermissionResult.NEUTRAL return PermissionResult.NEUTRAL
class IAMPolicyStatement(object): class IAMPolicyStatement:
def __init__(self, statement): def __init__(self, statement: Any):
self._statement = statement self._statement = statement
def is_action_permitted(self, action, resource="*"): def is_action_permitted(
self, action: str, resource: str = "*"
) -> "PermissionResult":
is_action_concerned = False is_action_concerned = False
if "NotAction" in self._statement: if "NotAction" in self._statement:
@ -386,7 +404,7 @@ class IAMPolicyStatement(object):
else: else:
return PermissionResult.NEUTRAL return PermissionResult.NEUTRAL
def is_unknown_principal(self, principal) -> bool: def is_unknown_principal(self, principal: Optional[str]) -> bool:
# https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-bucket-user-policy-specifying-principal-intro.html # https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-bucket-user-policy-specifying-principal-intro.html
# For now, Moto only verifies principal == * # For now, Moto only verifies principal == *
# 'Unknown' principals are not verified # 'Unknown' principals are not verified
@ -401,17 +419,17 @@ class IAMPolicyStatement(object):
return True return True
return False return False
def _check_element_matches(self, statement_element, value): def _check_element_matches(self, statement_element: Any, value: str) -> bool:
if isinstance(self._statement[statement_element], list): if isinstance(self._statement[statement_element], list):
for statement_element_value in self._statement[statement_element]: for statement_element_value in self._statement[statement_element]:
if self._match(statement_element_value, value): if self._match(statement_element_value, value):
return True return True
return False return False
else: # string else: # string
return self._match(self._statement[statement_element], value) return self._match(self._statement[statement_element], value) is not None
@staticmethod @staticmethod
def _match(pattern, string): def _match(pattern: str, string: str) -> Optional[Match[str]]:
pattern = pattern.replace("*", ".*") pattern = pattern.replace("*", ".*")
pattern = f"^{pattern}$" pattern = f"^{pattern}$"
return re.match(pattern, string) return re.match(pattern, string)

View File

@ -1,5 +1,6 @@
import json import json
import boto3 import boto3
from typing import Any, Dict, List, Optional, Tuple
from moto.core.exceptions import InvalidNextTokenException from moto.core.exceptions import InvalidNextTokenException
from moto.core.common_models import ConfigQueryModel from moto.core.common_models import ConfigQueryModel
from moto.iam import iam_backends from moto.iam import iam_backends
@ -8,15 +9,15 @@ from moto.iam import iam_backends
class RoleConfigQuery(ConfigQueryModel): class RoleConfigQuery(ConfigQueryModel):
def list_config_service_resources( def list_config_service_resources(
self, self,
account_id, account_id: str,
resource_ids, resource_ids: Optional[List[str]],
resource_name, resource_name: Optional[str],
limit, limit: int,
next_token, next_token: Optional[str],
backend_region=None, backend_region: Optional[str] = None,
resource_region=None, resource_region: Optional[str] = None,
aggregator=None, aggregator: Optional[Dict[str, Any]] = None,
): ) -> Tuple[List[Dict[str, Any]], Optional[str]]:
# IAM roles are "global" and aren't assigned into any availability zone # IAM roles are "global" and aren't assigned into any availability zone
# The resource ID is a AWS-assigned random string like "AROA0BSVNSZKXVHS00SBJ" # The resource ID is a AWS-assigned random string like "AROA0BSVNSZKXVHS00SBJ"
# The resource name is a user-assigned string like "MyDevelopmentAdminRole" # The resource name is a user-assigned string like "MyDevelopmentAdminRole"
@ -43,7 +44,7 @@ class RoleConfigQuery(ConfigQueryModel):
return [], None return [], None
else: else:
for role in role_list: for role in role_list:
if role.id in resource_ids: if role.id in resource_ids: # type: ignore[operator]
filtered_roles.append(role) filtered_roles.append(role)
# Filtered roles are now the subject for the listing # Filtered roles are now the subject for the listing
@ -60,7 +61,7 @@ class RoleConfigQuery(ConfigQueryModel):
aggregator_sources = aggregator.get( aggregator_sources = aggregator.get(
"account_aggregation_sources" "account_aggregation_sources"
) or aggregator.get("organization_aggregation_source") ) or aggregator.get("organization_aggregation_source")
for source in aggregator_sources: for source in aggregator_sources: # type: ignore[union-attr]
source_dict = source.__dict__ source_dict = source.__dict__
if source_dict.get("all_aws_regions", False): if source_dict.get("all_aws_regions", False):
aggregated_regions = boto3.Session().get_available_regions("config") aggregated_regions = boto3.Session().get_available_regions("config")
@ -86,7 +87,7 @@ class RoleConfigQuery(ConfigQueryModel):
else: else:
# Non-aggregated queries are in the else block, and we can treat these like a normal config resource # Non-aggregated queries are in the else block, and we can treat these like a normal config resource
# Pagination logic, sort by role id # Pagination logic, sort by role id
sorted_roles = sorted(role_list, key=lambda role: role.id) sorted_roles = sorted(role_list, key=lambda role: role.id) # type: ignore[attr-defined]
new_token = None new_token = None
@ -99,7 +100,7 @@ class RoleConfigQuery(ConfigQueryModel):
start = next( start = next(
index index
for (index, r) in enumerate(sorted_roles) for (index, r) in enumerate(sorted_roles)
if next_token == (r["_id"] if aggregator else r.id) if next_token == (r["_id"] if aggregator else r.id) # type: ignore[attr-defined]
) )
except StopIteration: except StopIteration:
raise InvalidNextTokenException() raise InvalidNextTokenException()
@ -109,14 +110,14 @@ class RoleConfigQuery(ConfigQueryModel):
if len(sorted_roles) > (start + limit): if len(sorted_roles) > (start + limit):
record = sorted_roles[start + limit] record = sorted_roles[start + limit]
new_token = record["_id"] if aggregator else record.id new_token = record["_id"] if aggregator else record.id # type: ignore[attr-defined]
return ( return (
[ [
{ {
"type": "AWS::IAM::Role", "type": "AWS::IAM::Role",
"id": role["id"] if aggregator else role.id, "id": role["id"] if aggregator else role.id, # type: ignore[attr-defined]
"name": role["name"] if aggregator else role.name, "name": role["name"] if aggregator else role.name, # type: ignore[attr-defined]
"region": role["region"] if aggregator else "global", "region": role["region"] if aggregator else "global",
} }
for role in role_list for role in role_list
@ -126,20 +127,20 @@ class RoleConfigQuery(ConfigQueryModel):
def get_config_resource( def get_config_resource(
self, self,
account_id, account_id: str,
resource_id, resource_id: str,
resource_name=None, resource_name: Optional[str] = None,
backend_region=None, backend_region: Optional[str] = None,
resource_region=None, resource_region: Optional[str] = None,
): ) -> Optional[Dict[str, Any]]:
role = self.backends[account_id]["global"].roles.get(resource_id, {}) role = self.backends[account_id]["global"].roles.get(resource_id, {})
if not role: if not role:
return return None
if resource_name and role.name != resource_name: if resource_name and role.name != resource_name:
return return None
# Format the role to the AWS Config format: # Format the role to the AWS Config format:
config_data = role.to_config_dict() config_data = role.to_config_dict()
@ -158,15 +159,15 @@ class RoleConfigQuery(ConfigQueryModel):
class PolicyConfigQuery(ConfigQueryModel): class PolicyConfigQuery(ConfigQueryModel):
def list_config_service_resources( def list_config_service_resources(
self, self,
account_id, account_id: str,
resource_ids, resource_ids: Optional[List[str]],
resource_name, resource_name: Optional[str],
limit, limit: int,
next_token, next_token: Optional[str],
backend_region=None, backend_region: Optional[str] = None,
resource_region=None, resource_region: Optional[str] = None,
aggregator=None, aggregator: Optional[Dict[str, Any]] = None,
): ) -> Tuple[List[Dict[str, Any]], Optional[str]]:
# IAM policies are "global" and aren't assigned into any availability zone # IAM policies are "global" and aren't assigned into any availability zone
# The resource ID is a AWS-assigned random string like "ANPA0BSVNSZK00SJSPVUJ" # The resource ID is a AWS-assigned random string like "ANPA0BSVNSZK00SJSPVUJ"
# The resource name is a user-assigned string like "my-development-policy" # The resource name is a user-assigned string like "my-development-policy"
@ -206,7 +207,7 @@ class PolicyConfigQuery(ConfigQueryModel):
else: else:
for policy in policy_list: for policy in policy_list:
if policy.id in resource_ids: if policy.id in resource_ids: # type: ignore[operator]
filtered_policies.append(policy) filtered_policies.append(policy)
# Filtered roles are now the subject for the listing # Filtered roles are now the subject for the listing
@ -223,7 +224,7 @@ class PolicyConfigQuery(ConfigQueryModel):
aggregator_sources = aggregator.get( aggregator_sources = aggregator.get(
"account_aggregation_sources" "account_aggregation_sources"
) or aggregator.get("organization_aggregation_source") ) or aggregator.get("organization_aggregation_source")
for source in aggregator_sources: for source in aggregator_sources: # type: ignore[union-attr]
source_dict = source.__dict__ source_dict = source.__dict__
if source_dict.get("all_aws_regions", False): if source_dict.get("all_aws_regions", False):
aggregated_regions = boto3.Session().get_available_regions("config") aggregated_regions = boto3.Session().get_available_regions("config")
@ -252,7 +253,7 @@ class PolicyConfigQuery(ConfigQueryModel):
else: else:
# Non-aggregated queries are in the else block, and we can treat these like a normal config resource # Non-aggregated queries are in the else block, and we can treat these like a normal config resource
# Pagination logic, sort by role id # Pagination logic, sort by role id
sorted_policies = sorted(policy_list, key=lambda role: role.id) sorted_policies = sorted(policy_list, key=lambda role: role.id) # type: ignore[attr-defined]
new_token = None new_token = None
@ -265,7 +266,7 @@ class PolicyConfigQuery(ConfigQueryModel):
start = next( start = next(
index index
for (index, p) in enumerate(sorted_policies) for (index, p) in enumerate(sorted_policies)
if next_token == (p["_id"] if aggregator else p.id) if next_token == (p["_id"] if aggregator else p.id) # type: ignore[attr-defined]
) )
except StopIteration: except StopIteration:
raise InvalidNextTokenException() raise InvalidNextTokenException()
@ -275,14 +276,14 @@ class PolicyConfigQuery(ConfigQueryModel):
if len(sorted_policies) > (start + limit): if len(sorted_policies) > (start + limit):
record = sorted_policies[start + limit] record = sorted_policies[start + limit]
new_token = record["_id"] if aggregator else record.id new_token = record["_id"] if aggregator else record.id # type: ignore[attr-defined]
return ( return (
[ [
{ {
"type": "AWS::IAM::Policy", "type": "AWS::IAM::Policy",
"id": policy["id"] if aggregator else policy.id, "id": policy["id"] if aggregator else policy.id, # type: ignore[attr-defined]
"name": policy["name"] if aggregator else policy.name, "name": policy["name"] if aggregator else policy.name, # type: ignore[attr-defined]
"region": policy["region"] if aggregator else "global", "region": policy["region"] if aggregator else "global",
} }
for policy in policy_list for policy in policy_list
@ -292,12 +293,12 @@ class PolicyConfigQuery(ConfigQueryModel):
def get_config_resource( def get_config_resource(
self, self,
account_id, account_id: str,
resource_id, resource_id: str,
resource_name=None, resource_name: Optional[str] = None,
backend_region=None, backend_region: Optional[str] = None,
resource_region=None, resource_region: Optional[str] = None,
): ) -> Optional[Dict[str, Any]]:
# policies are listed in the backend as arns, but we have to accept the PolicyID as the resource_id # policies are listed in the backend as arns, but we have to accept the PolicyID as the resource_id
# we'll make a really crude search for it # we'll make a really crude search for it
policy = None policy = None
@ -308,10 +309,10 @@ class PolicyConfigQuery(ConfigQueryModel):
break break
if not policy: if not policy:
return return None
if resource_name and policy.name != resource_name: if resource_name and policy.name != resource_name:
return return None
# Format the policy to the AWS Config format: # Format the policy to the AWS Config format:
config_data = policy.to_config_dict() config_data = policy.to_config_dict()

View File

@ -1,3 +1,4 @@
from typing import Any
from moto.core.exceptions import RESTError from moto.core.exceptions import RESTError
XMLNS_IAM = "https://iam.amazonaws.com/doc/2010-05-08/" XMLNS_IAM = "https://iam.amazonaws.com/doc/2010-05-08/"
@ -15,28 +16,28 @@ class IAMNotFoundException(RESTError):
class IAMConflictException(RESTError): class IAMConflictException(RESTError):
code = 409 code = 409
def __init__(self, code="Conflict", message=""): def __init__(self, code: str = "Conflict", message: str = ""):
super().__init__(code, message) super().__init__(code, message)
class IAMReportNotPresentException(RESTError): class IAMReportNotPresentException(RESTError):
code = 410 code = 410
def __init__(self, message): def __init__(self, message: str):
super().__init__("ReportNotPresent", message) super().__init__("ReportNotPresent", message)
class IAMLimitExceededException(RESTError): class IAMLimitExceededException(RESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("LimitExceeded", message) super().__init__("LimitExceeded", message)
class MalformedCertificate(RESTError): class MalformedCertificate(RESTError):
code = 400 code = 400
def __init__(self, cert): def __init__(self, cert: str):
super().__init__("MalformedCertificate", f"Certificate {cert} is malformed") super().__init__("MalformedCertificate", f"Certificate {cert} is malformed")
@ -55,7 +56,7 @@ class MalformedPolicyDocument(RESTError):
class DuplicateTags(RESTError): class DuplicateTags(RESTError):
code = 400 code = 400
def __init__(self): def __init__(self) -> None:
super().__init__( super().__init__(
"InvalidInput", "InvalidInput",
"Duplicate tag keys found. Please note that Tag keys are case insensitive.", "Duplicate tag keys found. Please note that Tag keys are case insensitive.",
@ -65,7 +66,7 @@ class DuplicateTags(RESTError):
class TagKeyTooBig(RESTError): class TagKeyTooBig(RESTError):
code = 400 code = 400
def __init__(self, tag, param="tags.X.member.key"): def __init__(self, tag: str, param: str = "tags.X.member.key"):
super().__init__( super().__init__(
"ValidationError", "ValidationError",
f"1 validation error detected: Value '{tag}' at '{param}' failed to satisfy " f"1 validation error detected: Value '{tag}' at '{param}' failed to satisfy "
@ -76,7 +77,7 @@ class TagKeyTooBig(RESTError):
class TagValueTooBig(RESTError): class TagValueTooBig(RESTError):
code = 400 code = 400
def __init__(self, tag): def __init__(self, tag: str):
super().__init__( super().__init__(
"ValidationError", "ValidationError",
f"1 validation error detected: Value '{tag}' at 'tags.X.member.value' failed to satisfy " f"1 validation error detected: Value '{tag}' at 'tags.X.member.value' failed to satisfy "
@ -87,7 +88,7 @@ class TagValueTooBig(RESTError):
class InvalidTagCharacters(RESTError): class InvalidTagCharacters(RESTError):
code = 400 code = 400
def __init__(self, tag, param="tags.X.member.key"): def __init__(self, tag: str, param: str = "tags.X.member.key"):
message = f"1 validation error detected: Value '{tag}' at '{param}' failed to satisfy constraint: Member must satisfy regular expression pattern: [\\p{{L}}\\p{{Z}}\\p{{N}}_.:/=+\\-@]+" message = f"1 validation error detected: Value '{tag}' at '{param}' failed to satisfy constraint: Member must satisfy regular expression pattern: [\\p{{L}}\\p{{Z}}\\p{{N}}_.:/=+\\-@]+"
super().__init__("ValidationError", message) super().__init__("ValidationError", message)
@ -96,7 +97,7 @@ class InvalidTagCharacters(RESTError):
class TooManyTags(RESTError): class TooManyTags(RESTError):
code = 400 code = 400
def __init__(self, tags, param="tags"): def __init__(self, tags: Any, param: str = "tags"):
super().__init__( super().__init__(
"ValidationError", "ValidationError",
f"1 validation error detected: Value '{tags}' at '{param}' failed to satisfy " f"1 validation error detected: Value '{tags}' at '{param}' failed to satisfy "
@ -107,28 +108,28 @@ class TooManyTags(RESTError):
class EntityAlreadyExists(RESTError): class EntityAlreadyExists(RESTError):
code = 409 code = 409
def __init__(self, message): def __init__(self, message: str):
super().__init__("EntityAlreadyExists", message) super().__init__("EntityAlreadyExists", message)
class ValidationError(RESTError): class ValidationError(RESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("ValidationError", message) super().__init__("ValidationError", message)
class InvalidInput(RESTError): class InvalidInput(RESTError):
code = 400 code = 400
def __init__(self, message): def __init__(self, message: str):
super().__init__("InvalidInput", message) super().__init__("InvalidInput", message)
class NoSuchEntity(RESTError): class NoSuchEntity(RESTError):
code = 404 code = 404
def __init__(self, message): def __init__(self, message: str):
super().__init__( super().__init__(
"NoSuchEntity", message, xmlns=XMLNS_IAM, template="wrapped_single_error" "NoSuchEntity", message, xmlns=XMLNS_IAM, template="wrapped_single_error"
) )

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import json import json
import re import re
from typing import Any, Dict, List
from moto.iam.exceptions import MalformedPolicyDocument from moto.iam.exceptions import MalformedPolicyDocument
@ -61,7 +61,7 @@ SERVICE_TYPE_REGION_INFORMATION_ERROR_ASSOCIATIONS = {
"s3": "Resource {resource} can not contain region information.", "s3": "Resource {resource} can not contain region information.",
} }
VALID_RESOURCE_PATH_STARTING_VALUES = { VALID_RESOURCE_PATH_STARTING_VALUES: Dict[str, Any] = {
"iam": { "iam": {
"values": [ "values": [
"user/", "user/",
@ -84,13 +84,13 @@ VALID_RESOURCE_PATH_STARTING_VALUES = {
class BaseIAMPolicyValidator: class BaseIAMPolicyValidator:
def __init__(self, policy_document): def __init__(self, policy_document: str):
self._policy_document = policy_document self._policy_document = policy_document
self._policy_json = {} self._policy_json: Dict[str, Any] = {}
self._statements = [] self._statements: List[Dict[str, Any]] = []
self._resource_error = "" # the first resource error found that does not generate a legacy parsing error self._resource_error = "" # the first resource error found that does not generate a legacy parsing error
def validate(self): def validate(self) -> None:
try: try:
self._validate_syntax() self._validate_syntax()
except Exception: except Exception:
@ -124,7 +124,7 @@ class BaseIAMPolicyValidator:
self._validate_actions_for_prefixes() self._validate_actions_for_prefixes()
self._validate_not_actions_for_prefixes() self._validate_not_actions_for_prefixes()
def _validate_syntax(self): def _validate_syntax(self) -> None:
self._policy_json = json.loads(self._policy_document) self._policy_json = json.loads(self._policy_document)
assert isinstance(self._policy_json, dict) assert isinstance(self._policy_json, dict)
self._validate_top_elements() self._validate_top_elements()
@ -132,19 +132,19 @@ class BaseIAMPolicyValidator:
self._validate_id_syntax() self._validate_id_syntax()
self._validate_statements_syntax() self._validate_statements_syntax()
def _validate_top_elements(self): def _validate_top_elements(self) -> None:
top_elements = self._policy_json.keys() top_elements = self._policy_json.keys()
for element in top_elements: for element in top_elements:
assert element in VALID_TOP_ELEMENTS assert element in VALID_TOP_ELEMENTS
def _validate_version_syntax(self): def _validate_version_syntax(self) -> None:
if "Version" in self._policy_json: if "Version" in self._policy_json:
assert self._policy_json["Version"] in VALID_VERSIONS assert self._policy_json["Version"] in VALID_VERSIONS
def _validate_version(self): def _validate_version(self) -> None:
assert self._policy_json["Version"] == "2012-10-17" assert self._policy_json["Version"] == "2012-10-17"
def _validate_sid_uniqueness(self): def _validate_sid_uniqueness(self) -> None:
sids = [] sids = []
for statement in self._statements: for statement in self._statements:
if "Sid" in statement: if "Sid" in statement:
@ -153,7 +153,7 @@ class BaseIAMPolicyValidator:
assert statementId not in sids assert statementId not in sids
sids.append(statementId) sids.append(statementId)
def _validate_statements_syntax(self): def _validate_statements_syntax(self) -> None:
assert "Statement" in self._policy_json assert "Statement" in self._policy_json
assert isinstance(self._policy_json["Statement"], (dict, list)) assert isinstance(self._policy_json["Statement"], (dict, list))
@ -167,7 +167,7 @@ class BaseIAMPolicyValidator:
self._validate_statement_syntax(statement) self._validate_statement_syntax(statement)
@staticmethod @staticmethod
def _validate_statement_syntax(statement): def _validate_statement_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
assert isinstance(statement, dict) assert isinstance(statement, dict)
for statement_element in statement.keys(): for statement_element in statement.keys():
assert statement_element in VALID_STATEMENT_ELEMENTS assert statement_element in VALID_STATEMENT_ELEMENTS
@ -184,7 +184,7 @@ class BaseIAMPolicyValidator:
IAMPolicyDocumentValidator._validate_sid_syntax(statement) IAMPolicyDocumentValidator._validate_sid_syntax(statement)
@staticmethod @staticmethod
def _validate_effect_syntax(statement): def _validate_effect_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
assert "Effect" in statement assert "Effect" in statement
assert isinstance(statement["Effect"], str) assert isinstance(statement["Effect"], str)
assert statement["Effect"].lower() in [ assert statement["Effect"].lower() in [
@ -192,31 +192,31 @@ class BaseIAMPolicyValidator:
] ]
@staticmethod @staticmethod
def _validate_action_syntax(statement): def _validate_action_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax( IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "Action" statement, "Action"
) )
@staticmethod @staticmethod
def _validate_not_action_syntax(statement): def _validate_not_action_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax( IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "NotAction" statement, "NotAction"
) )
@staticmethod @staticmethod
def _validate_resource_syntax(statement): def _validate_resource_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax( IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "Resource" statement, "Resource"
) )
@staticmethod @staticmethod
def _validate_not_resource_syntax(statement): def _validate_not_resource_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax( IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "NotResource" statement, "NotResource"
) )
@staticmethod @staticmethod
def _validate_string_or_list_of_strings_syntax(statement, key): def _validate_string_or_list_of_strings_syntax(statement: Dict[str, Any], key: str) -> None: # type: ignore[misc]
if key in statement: if key in statement:
assert isinstance(statement[key], (str, list)) assert isinstance(statement[key], (str, list))
if isinstance(statement[key], list): if isinstance(statement[key], list):
@ -224,7 +224,7 @@ class BaseIAMPolicyValidator:
assert isinstance(resource, str) assert isinstance(resource, str)
@staticmethod @staticmethod
def _validate_condition_syntax(statement): def _validate_condition_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
if "Condition" in statement: if "Condition" in statement:
assert isinstance(statement["Condition"], dict) assert isinstance(statement["Condition"], dict)
for condition_key, condition_value in statement["Condition"].items(): for condition_key, condition_value in statement["Condition"].items():
@ -239,7 +239,7 @@ class BaseIAMPolicyValidator:
assert not condition_value # empty dict assert not condition_value # empty dict
@staticmethod @staticmethod
def _strip_condition_key(condition_key): def _strip_condition_key(condition_key: str) -> str:
for valid_prefix in VALID_CONDITION_PREFIXES: for valid_prefix in VALID_CONDITION_PREFIXES:
if condition_key.startswith(valid_prefix): if condition_key.startswith(valid_prefix):
condition_key = condition_key[len(valid_prefix) :] condition_key = condition_key[len(valid_prefix) :]
@ -253,15 +253,15 @@ class BaseIAMPolicyValidator:
return condition_key return condition_key
@staticmethod @staticmethod
def _validate_sid_syntax(statement): def _validate_sid_syntax(statement: Dict[str, Any]) -> None: # type: ignore[misc]
if "Sid" in statement: if "Sid" in statement:
assert isinstance(statement["Sid"], str) assert isinstance(statement["Sid"], str)
def _validate_id_syntax(self): def _validate_id_syntax(self) -> None:
if "Id" in self._policy_json: if "Id" in self._policy_json:
assert isinstance(self._policy_json["Id"], str) assert isinstance(self._policy_json["Id"], str)
def _validate_resource_exist(self): def _validate_resource_exist(self) -> None:
for statement in self._statements: for statement in self._statements:
assert "Resource" in statement or "NotResource" in statement assert "Resource" in statement or "NotResource" in statement
if "Resource" in statement and isinstance(statement["Resource"], list): if "Resource" in statement and isinstance(statement["Resource"], list):
@ -271,7 +271,7 @@ class BaseIAMPolicyValidator:
): ):
assert statement["NotResource"] assert statement["NotResource"]
def _validate_action_like_exist(self): def _validate_action_like_exist(self) -> None:
for statement in self._statements: for statement in self._statements:
assert "Action" in statement or "NotAction" in statement assert "Action" in statement or "NotAction" in statement
if "Action" in statement and isinstance(statement["Action"], list): if "Action" in statement and isinstance(statement["Action"], list):
@ -279,13 +279,13 @@ class BaseIAMPolicyValidator:
elif "NotAction" in statement and isinstance(statement["NotAction"], list): elif "NotAction" in statement and isinstance(statement["NotAction"], list):
assert statement["NotAction"] assert statement["NotAction"]
def _validate_actions_for_prefixes(self): def _validate_actions_for_prefixes(self) -> None:
self._validate_action_like_for_prefixes("Action") self._validate_action_like_for_prefixes("Action")
def _validate_not_actions_for_prefixes(self): def _validate_not_actions_for_prefixes(self) -> None:
self._validate_action_like_for_prefixes("NotAction") self._validate_action_like_for_prefixes("NotAction")
def _validate_action_like_for_prefixes(self, key): def _validate_action_like_for_prefixes(self, key: str) -> None:
for statement in self._statements: for statement in self._statements:
if key in statement: if key in statement:
if isinstance(statement[key], str): if isinstance(statement[key], str):
@ -295,7 +295,7 @@ class BaseIAMPolicyValidator:
self._validate_action_prefix(action) self._validate_action_prefix(action)
@staticmethod @staticmethod
def _validate_action_prefix(action): def _validate_action_prefix(action: str) -> None:
action_parts = action.split(":") action_parts = action.split(":")
if len(action_parts) == 1 and action_parts[0] != "*": if len(action_parts) == 1 and action_parts[0] != "*":
raise MalformedPolicyDocument( raise MalformedPolicyDocument(
@ -310,13 +310,13 @@ class BaseIAMPolicyValidator:
if action_parts[0] != "*" and vendor_pattern.search(action_parts[0]): if action_parts[0] != "*" and vendor_pattern.search(action_parts[0]):
raise MalformedPolicyDocument(f"Vendor {action_parts[0]} is not valid") raise MalformedPolicyDocument(f"Vendor {action_parts[0]} is not valid")
def _validate_resources_for_formats(self): def _validate_resources_for_formats(self) -> None:
self._validate_resource_like_for_formats("Resource") self._validate_resource_like_for_formats("Resource")
def _validate_not_resources_for_formats(self): def _validate_not_resources_for_formats(self) -> None:
self._validate_resource_like_for_formats("NotResource") self._validate_resource_like_for_formats("NotResource")
def _validate_resource_like_for_formats(self, key): def _validate_resource_like_for_formats(self, key: str) -> None:
for statement in self._statements: for statement in self._statements:
if key in statement: if key in statement:
if isinstance(statement[key], str): if isinstance(statement[key], str):
@ -329,7 +329,7 @@ class BaseIAMPolicyValidator:
statement, key statement, key
) )
def _validate_resource_format(self, resource): def _validate_resource_format(self, resource: str) -> None:
if resource != "*": if resource != "*":
resource_partitions = resource.partition(":") resource_partitions = resource.partition(":")
@ -407,13 +407,13 @@ class BaseIAMPolicyValidator:
) )
) )
def _perform_first_legacy_parsing(self): def _perform_first_legacy_parsing(self) -> None:
"""This method excludes legacy parsing resources, since that have to be done later.""" """This method excludes legacy parsing resources, since that have to be done later."""
for statement in self._statements: for statement in self._statements:
self._legacy_parse_statement(statement) self._legacy_parse_statement(statement)
@staticmethod @staticmethod
def _legacy_parse_statement(statement): def _legacy_parse_statement(statement: Dict[str, Any]) -> None: # type: ignore[misc]
assert statement["Effect"] in VALID_EFFECTS # case-sensitive matching assert statement["Effect"] in VALID_EFFECTS # case-sensitive matching
if "Condition" in statement: if "Condition" in statement:
for condition_key, condition_value in statement["Condition"].items(): for condition_key, condition_value in statement["Condition"].items():
@ -422,7 +422,7 @@ class BaseIAMPolicyValidator:
) )
@staticmethod @staticmethod
def _legacy_parse_resource_like(statement, key): def _legacy_parse_resource_like(statement: Dict[str, Any], key: str) -> None: # type: ignore[misc]
if isinstance(statement[key], str): if isinstance(statement[key], str):
if statement[key] != "*": if statement[key] != "*":
assert statement[key].count(":") >= 5 or "::" not in statement[key] assert statement[key].count(":") >= 5 or "::" not in statement[key]
@ -434,7 +434,7 @@ class BaseIAMPolicyValidator:
assert resource[2] != "" assert resource[2] != ""
@staticmethod @staticmethod
def _legacy_parse_condition(condition_key, condition_value): def _legacy_parse_condition(condition_key: str, condition_value: Dict[str, Any]) -> None: # type: ignore[misc]
stripped_condition_key = IAMPolicyDocumentValidator._strip_condition_key( stripped_condition_key = IAMPolicyDocumentValidator._strip_condition_key(
condition_key condition_key
) )
@ -452,7 +452,7 @@ class BaseIAMPolicyValidator:
) )
@staticmethod @staticmethod
def _legacy_parse_date_condition_value(date_condition_value): def _legacy_parse_date_condition_value(date_condition_value: str) -> None:
if "t" in date_condition_value.lower() or "-" in date_condition_value: if "t" in date_condition_value.lower() or "-" in date_condition_value:
IAMPolicyDocumentValidator._validate_iso_8601_datetime( IAMPolicyDocumentValidator._validate_iso_8601_datetime(
date_condition_value.lower() date_condition_value.lower()
@ -461,7 +461,7 @@ class BaseIAMPolicyValidator:
assert 0 <= int(date_condition_value) <= 9223372036854775807 assert 0 <= int(date_condition_value) <= 9223372036854775807
@staticmethod @staticmethod
def _validate_iso_8601_datetime(datetime): def _validate_iso_8601_datetime(datetime: str) -> None:
datetime_parts = datetime.partition("t") datetime_parts = datetime.partition("t")
negative_year = datetime_parts[0].startswith("-") negative_year = datetime_parts[0].startswith("-")
date_parts = ( date_parts = (
@ -525,10 +525,10 @@ class IAMPolicyDocumentValidator(BaseIAMPolicyValidator):
class IAMTrustPolicyDocumentValidator(BaseIAMPolicyValidator): class IAMTrustPolicyDocumentValidator(BaseIAMPolicyValidator):
def __init__(self, policy_document): def __init__(self, policy_document: str):
super().__init__(policy_document) super().__init__(policy_document)
def validate(self): def validate(self) -> None:
super().validate() super().validate()
try: try:
for statement in self._statements: for statement in self._statements:
@ -551,12 +551,12 @@ class IAMTrustPolicyDocumentValidator(BaseIAMPolicyValidator):
except Exception: except Exception:
raise MalformedPolicyDocument("Has prohibited field Resource.") raise MalformedPolicyDocument("Has prohibited field Resource.")
def _validate_resource_not_exist(self): def _validate_resource_not_exist(self) -> None:
for statement in self._statements: for statement in self._statements:
assert "Resource" not in statement and "NotResource" not in statement assert "Resource" not in statement and "NotResource" not in statement
@staticmethod @staticmethod
def _validate_trust_policy_action(action): def _validate_trust_policy_action(action: str) -> None:
# https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssecuritytokenservice.html # https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssecuritytokenservice.html
assert action in ( assert action in (
"sts:AssumeRole", "sts:AssumeRole",

View File

@ -1,59 +1,59 @@
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import iam_backends, User from .models import iam_backends, IAMBackend, User
class IamResponse(BaseResponse): class IamResponse(BaseResponse):
def __init__(self): def __init__(self) -> None:
super().__init__(service_name="iam") super().__init__(service_name="iam")
@property @property
def backend(self): def backend(self) -> IAMBackend:
return iam_backends[self.current_account]["global"] return iam_backends[self.current_account]["global"]
def attach_role_policy(self): def attach_role_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
self.backend.attach_role_policy(policy_arn, role_name) self.backend.attach_role_policy(policy_arn, role_name)
template = self.response_template(ATTACH_ROLE_POLICY_TEMPLATE) template = self.response_template(ATTACH_ROLE_POLICY_TEMPLATE)
return template.render() return template.render()
def detach_role_policy(self): def detach_role_policy(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
self.backend.detach_role_policy(policy_arn, role_name) self.backend.detach_role_policy(policy_arn, role_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DetachRolePolicy") return template.render(name="DetachRolePolicy")
def attach_group_policy(self): def attach_group_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
self.backend.attach_group_policy(policy_arn, group_name) self.backend.attach_group_policy(policy_arn, group_name)
template = self.response_template(ATTACH_GROUP_POLICY_TEMPLATE) template = self.response_template(ATTACH_GROUP_POLICY_TEMPLATE)
return template.render() return template.render()
def detach_group_policy(self): def detach_group_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
self.backend.detach_group_policy(policy_arn, group_name) self.backend.detach_group_policy(policy_arn, group_name)
template = self.response_template(DETACH_GROUP_POLICY_TEMPLATE) template = self.response_template(DETACH_GROUP_POLICY_TEMPLATE)
return template.render() return template.render()
def attach_user_policy(self): def attach_user_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
self.backend.attach_user_policy(policy_arn, user_name) self.backend.attach_user_policy(policy_arn, user_name)
template = self.response_template(ATTACH_USER_POLICY_TEMPLATE) template = self.response_template(ATTACH_USER_POLICY_TEMPLATE)
return template.render() return template.render()
def detach_user_policy(self): def detach_user_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
self.backend.detach_user_policy(policy_arn, user_name) self.backend.detach_user_policy(policy_arn, user_name)
template = self.response_template(DETACH_USER_POLICY_TEMPLATE) template = self.response_template(DETACH_USER_POLICY_TEMPLATE)
return template.render() return template.render()
def create_policy(self): def create_policy(self) -> str:
description = self._get_param("Description") description = self._get_param("Description")
path = self._get_param("Path") path = self._get_param("Path")
policy_document = self._get_param("PolicyDocument") policy_document = self._get_param("PolicyDocument")
@ -65,13 +65,13 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_POLICY_TEMPLATE) template = self.response_template(CREATE_POLICY_TEMPLATE)
return template.render(policy=policy) return template.render(policy=policy)
def get_policy(self): def get_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
policy = self.backend.get_policy(policy_arn) policy = self.backend.get_policy(policy_arn)
template = self.response_template(GET_POLICY_TEMPLATE) template = self.response_template(GET_POLICY_TEMPLATE)
return template.render(policy=policy) return template.render(policy=policy)
def list_attached_role_policies(self): def list_attached_role_policies(self) -> str:
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_int_param("MaxItems", 100) max_items = self._get_int_param("MaxItems", 100)
path_prefix = self._get_param("PathPrefix", "/") path_prefix = self._get_param("PathPrefix", "/")
@ -82,7 +82,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_ATTACHED_ROLE_POLICIES_TEMPLATE) template = self.response_template(LIST_ATTACHED_ROLE_POLICIES_TEMPLATE)
return template.render(policies=policies, marker=marker) return template.render(policies=policies, marker=marker)
def list_attached_group_policies(self): def list_attached_group_policies(self) -> str:
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_int_param("MaxItems", 100) max_items = self._get_int_param("MaxItems", 100)
path_prefix = self._get_param("PathPrefix", "/") path_prefix = self._get_param("PathPrefix", "/")
@ -93,7 +93,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_ATTACHED_GROUP_POLICIES_TEMPLATE) template = self.response_template(LIST_ATTACHED_GROUP_POLICIES_TEMPLATE)
return template.render(policies=policies, marker=marker) return template.render(policies=policies, marker=marker)
def list_attached_user_policies(self): def list_attached_user_policies(self) -> str:
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_int_param("MaxItems", 100) max_items = self._get_int_param("MaxItems", 100)
path_prefix = self._get_param("PathPrefix", "/") path_prefix = self._get_param("PathPrefix", "/")
@ -104,7 +104,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_ATTACHED_USER_POLICIES_TEMPLATE) template = self.response_template(LIST_ATTACHED_USER_POLICIES_TEMPLATE)
return template.render(policies=policies, marker=marker) return template.render(policies=policies, marker=marker)
def list_policies(self): def list_policies(self) -> str:
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_int_param("MaxItems", 100) max_items = self._get_int_param("MaxItems", 100)
only_attached = self._get_bool_param("OnlyAttached", False) only_attached = self._get_bool_param("OnlyAttached", False)
@ -116,7 +116,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_POLICIES_TEMPLATE) template = self.response_template(LIST_POLICIES_TEMPLATE)
return template.render(policies=policies, marker=marker) return template.render(policies=policies, marker=marker)
def list_entities_for_policy(self): def list_entities_for_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
# Options 'User'|'Role'|'Group'|'LocalManagedPolicy'|'AWSManagedPolicy # Options 'User'|'Role'|'Group'|'LocalManagedPolicy'|'AWSManagedPolicy
@ -181,14 +181,14 @@ class IamResponse(BaseResponse):
roles=entity_roles, users=entity_users, groups=entity_groups roles=entity_roles, users=entity_users, groups=entity_groups
) )
def set_default_policy_version(self): def set_default_policy_version(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
version_id = self._get_param("VersionId") version_id = self._get_param("VersionId")
self.backend.set_default_policy_version(policy_arn, version_id) self.backend.set_default_policy_version(policy_arn, version_id)
template = self.response_template(SET_DEFAULT_POLICY_VERSION_TEMPLATE) template = self.response_template(SET_DEFAULT_POLICY_VERSION_TEMPLATE)
return template.render() return template.render()
def create_role(self): def create_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
path = self._get_param("Path") path = self._get_param("Path")
assume_role_policy_document = self._get_param("AssumeRolePolicyDocument") assume_role_policy_document = self._get_param("AssumeRolePolicyDocument")
@ -209,26 +209,26 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_ROLE_TEMPLATE) template = self.response_template(CREATE_ROLE_TEMPLATE)
return template.render(role=role) return template.render(role=role)
def get_role(self): def get_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
role = self.backend.get_role(role_name) role = self.backend.get_role(role_name)
template = self.response_template(GET_ROLE_TEMPLATE) template = self.response_template(GET_ROLE_TEMPLATE)
return template.render(role=role) return template.render(role=role)
def delete_role(self): def delete_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
self.backend.delete_role(role_name) self.backend.delete_role(role_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteRole") return template.render(name="DeleteRole")
def list_role_policies(self): def list_role_policies(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
role_policies_names = self.backend.list_role_policies(role_name) role_policies_names = self.backend.list_role_policies(role_name)
template = self.response_template(LIST_ROLE_POLICIES) template = self.response_template(LIST_ROLE_POLICIES)
return template.render(role_policies=role_policies_names) return template.render(role_policies=role_policies_names)
def put_role_policy(self): def put_role_policy(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
policy_document = self._get_param("PolicyDocument") policy_document = self._get_param("PolicyDocument")
@ -236,14 +236,14 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="PutRolePolicy") return template.render(name="PutRolePolicy")
def delete_role_policy(self): def delete_role_policy(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
self.backend.delete_role_policy(role_name, policy_name) self.backend.delete_role_policy(role_name, policy_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteRolePolicy") return template.render(name="DeleteRolePolicy")
def get_role_policy(self): def get_role_policy(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
policy_name, policy_document = self.backend.get_role_policy( policy_name, policy_document = self.backend.get_role_policy(
@ -256,21 +256,21 @@ class IamResponse(BaseResponse):
policy_document=policy_document, policy_document=policy_document,
) )
def update_assume_role_policy(self): def update_assume_role_policy(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
policy_document = self._get_param("PolicyDocument") policy_document = self._get_param("PolicyDocument")
self.backend.update_assume_role_policy(role_name, policy_document) self.backend.update_assume_role_policy(role_name, policy_document)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="UpdateAssumeRolePolicy") return template.render(name="UpdateAssumeRolePolicy")
def update_role_description(self): def update_role_description(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
description = self._get_param("Description") description = self._get_param("Description")
role = self.backend.update_role_description(role_name, description) role = self.backend.update_role_description(role_name, description)
template = self.response_template(UPDATE_ROLE_DESCRIPTION_TEMPLATE) template = self.response_template(UPDATE_ROLE_DESCRIPTION_TEMPLATE)
return template.render(role=role) return template.render(role=role)
def update_role(self): def update_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
description = self._get_param("Description") description = self._get_param("Description")
max_session_duration = self._get_param("MaxSessionDuration", 3600) max_session_duration = self._get_param("MaxSessionDuration", 3600)
@ -278,20 +278,20 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_ROLE_TEMPLATE) template = self.response_template(UPDATE_ROLE_TEMPLATE)
return template.render(role=role) return template.render(role=role)
def put_role_permissions_boundary(self): def put_role_permissions_boundary(self) -> str:
permissions_boundary = self._get_param("PermissionsBoundary") permissions_boundary = self._get_param("PermissionsBoundary")
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
self.backend.put_role_permissions_boundary(role_name, permissions_boundary) self.backend.put_role_permissions_boundary(role_name, permissions_boundary)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="PutRolePermissionsBoundary") return template.render(name="PutRolePermissionsBoundary")
def delete_role_permissions_boundary(self): def delete_role_permissions_boundary(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
self.backend.delete_role_permissions_boundary(role_name) self.backend.delete_role_permissions_boundary(role_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteRolePermissionsBoundary") return template.render(name="DeleteRolePermissionsBoundary")
def create_policy_version(self): def create_policy_version(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
policy_document = self._get_param("PolicyDocument") policy_document = self._get_param("PolicyDocument")
set_as_default = self._get_param("SetAsDefault") set_as_default = self._get_param("SetAsDefault")
@ -301,21 +301,21 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_POLICY_VERSION_TEMPLATE) template = self.response_template(CREATE_POLICY_VERSION_TEMPLATE)
return template.render(policy_version=policy_version) return template.render(policy_version=policy_version)
def get_policy_version(self): def get_policy_version(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
version_id = self._get_param("VersionId") version_id = self._get_param("VersionId")
policy_version = self.backend.get_policy_version(policy_arn, version_id) policy_version = self.backend.get_policy_version(policy_arn, version_id)
template = self.response_template(GET_POLICY_VERSION_TEMPLATE) template = self.response_template(GET_POLICY_VERSION_TEMPLATE)
return template.render(policy_version=policy_version) return template.render(policy_version=policy_version)
def list_policy_versions(self): def list_policy_versions(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
policy_versions = self.backend.list_policy_versions(policy_arn) policy_versions = self.backend.list_policy_versions(policy_arn)
template = self.response_template(LIST_POLICY_VERSIONS_TEMPLATE) template = self.response_template(LIST_POLICY_VERSIONS_TEMPLATE)
return template.render(policy_versions=policy_versions) return template.render(policy_versions=policy_versions)
def list_policy_tags(self): def list_policy_tags(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_param("MaxItems", 100) max_items = self._get_param("MaxItems", 100)
@ -325,7 +325,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_POLICY_TAG_TEMPLATE) template = self.response_template(LIST_POLICY_TAG_TEMPLATE)
return template.render(tags=tags, marker=marker) return template.render(tags=tags, marker=marker)
def tag_policy(self): def tag_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
tags = self._get_multi_param("Tags.member") tags = self._get_multi_param("Tags.member")
@ -334,7 +334,7 @@ class IamResponse(BaseResponse):
template = self.response_template(TAG_POLICY_TEMPLATE) template = self.response_template(TAG_POLICY_TEMPLATE)
return template.render() return template.render()
def untag_policy(self): def untag_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
tag_keys = self._get_multi_param("TagKeys.member") tag_keys = self._get_multi_param("TagKeys.member")
@ -343,7 +343,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UNTAG_POLICY_TEMPLATE) template = self.response_template(UNTAG_POLICY_TEMPLATE)
return template.render() return template.render()
def delete_policy_version(self): def delete_policy_version(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
version_id = self._get_param("VersionId") version_id = self._get_param("VersionId")
@ -351,7 +351,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeletePolicyVersion") return template.render(name="DeletePolicyVersion")
def create_instance_profile(self): def create_instance_profile(self) -> str:
profile_name = self._get_param("InstanceProfileName") profile_name = self._get_param("InstanceProfileName")
path = self._get_param("Path", "/") path = self._get_param("Path", "/")
tags = self._get_multi_param("Tags.member") tags = self._get_multi_param("Tags.member")
@ -362,21 +362,21 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_INSTANCE_PROFILE_TEMPLATE) template = self.response_template(CREATE_INSTANCE_PROFILE_TEMPLATE)
return template.render(profile=profile) return template.render(profile=profile)
def delete_instance_profile(self): def delete_instance_profile(self) -> str:
profile_name = self._get_param("InstanceProfileName") profile_name = self._get_param("InstanceProfileName")
profile = self.backend.delete_instance_profile(profile_name) self.backend.delete_instance_profile(profile_name)
template = self.response_template(DELETE_INSTANCE_PROFILE_TEMPLATE) template = self.response_template(DELETE_INSTANCE_PROFILE_TEMPLATE)
return template.render(profile=profile) return template.render()
def get_instance_profile(self): def get_instance_profile(self) -> str:
profile_name = self._get_param("InstanceProfileName") profile_name = self._get_param("InstanceProfileName")
profile = self.backend.get_instance_profile(profile_name) profile = self.backend.get_instance_profile(profile_name)
template = self.response_template(GET_INSTANCE_PROFILE_TEMPLATE) template = self.response_template(GET_INSTANCE_PROFILE_TEMPLATE)
return template.render(profile=profile) return template.render(profile=profile)
def add_role_to_instance_profile(self): def add_role_to_instance_profile(self) -> str:
profile_name = self._get_param("InstanceProfileName") profile_name = self._get_param("InstanceProfileName")
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
@ -384,7 +384,7 @@ class IamResponse(BaseResponse):
template = self.response_template(ADD_ROLE_TO_INSTANCE_PROFILE_TEMPLATE) template = self.response_template(ADD_ROLE_TO_INSTANCE_PROFILE_TEMPLATE)
return template.render() return template.render()
def remove_role_from_instance_profile(self): def remove_role_from_instance_profile(self) -> str:
profile_name = self._get_param("InstanceProfileName") profile_name = self._get_param("InstanceProfileName")
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
@ -392,7 +392,7 @@ class IamResponse(BaseResponse):
template = self.response_template(REMOVE_ROLE_FROM_INSTANCE_PROFILE_TEMPLATE) template = self.response_template(REMOVE_ROLE_FROM_INSTANCE_PROFILE_TEMPLATE)
return template.render() return template.render()
def list_roles(self): def list_roles(self) -> str:
path_prefix = self._get_param("PathPrefix", "/") path_prefix = self._get_param("PathPrefix", "/")
marker = self._get_param("Marker", "0") marker = self._get_param("Marker", "0")
max_items = self._get_param("MaxItems", 100) max_items = self._get_param("MaxItems", 100)
@ -401,20 +401,20 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_ROLES_TEMPLATE) template = self.response_template(LIST_ROLES_TEMPLATE)
return template.render(roles=roles, marker=marker) return template.render(roles=roles, marker=marker)
def list_instance_profiles(self): def list_instance_profiles(self) -> str:
profiles = self.backend.get_instance_profiles() profiles = self.backend.get_instance_profiles()
template = self.response_template(LIST_INSTANCE_PROFILES_TEMPLATE) template = self.response_template(LIST_INSTANCE_PROFILES_TEMPLATE)
return template.render(instance_profiles=profiles) return template.render(instance_profiles=profiles)
def list_instance_profiles_for_role(self): def list_instance_profiles_for_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
profiles = self.backend.get_instance_profiles_for_role(role_name=role_name) profiles = self.backend.get_instance_profiles_for_role(role_name=role_name)
template = self.response_template(LIST_INSTANCE_PROFILES_FOR_ROLE_TEMPLATE) template = self.response_template(LIST_INSTANCE_PROFILES_FOR_ROLE_TEMPLATE)
return template.render(instance_profiles=profiles) return template.render(instance_profiles=profiles)
def upload_server_certificate(self): def upload_server_certificate(self) -> str:
cert_name = self._get_param("ServerCertificateName") cert_name = self._get_param("ServerCertificateName")
cert_body = self._get_param("CertificateBody") cert_body = self._get_param("CertificateBody")
path = self._get_param("Path") path = self._get_param("Path")
@ -427,24 +427,24 @@ class IamResponse(BaseResponse):
template = self.response_template(UPLOAD_CERT_TEMPLATE) template = self.response_template(UPLOAD_CERT_TEMPLATE)
return template.render(certificate=cert) return template.render(certificate=cert)
def list_server_certificates(self): def list_server_certificates(self) -> str:
certs = self.backend.list_server_certificates() certs = self.backend.list_server_certificates()
template = self.response_template(LIST_SERVER_CERTIFICATES_TEMPLATE) template = self.response_template(LIST_SERVER_CERTIFICATES_TEMPLATE)
return template.render(server_certificates=certs) return template.render(server_certificates=certs)
def get_server_certificate(self): def get_server_certificate(self) -> str:
cert_name = self._get_param("ServerCertificateName") cert_name = self._get_param("ServerCertificateName")
cert = self.backend.get_server_certificate(cert_name) cert = self.backend.get_server_certificate(cert_name)
template = self.response_template(GET_SERVER_CERTIFICATE_TEMPLATE) template = self.response_template(GET_SERVER_CERTIFICATE_TEMPLATE)
return template.render(certificate=cert) return template.render(certificate=cert)
def delete_server_certificate(self): def delete_server_certificate(self) -> str:
cert_name = self._get_param("ServerCertificateName") cert_name = self._get_param("ServerCertificateName")
self.backend.delete_server_certificate(cert_name) self.backend.delete_server_certificate(cert_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteServerCertificate") return template.render(name="DeleteServerCertificate")
def create_group(self): def create_group(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
path = self._get_param("Path", "/") path = self._get_param("Path", "/")
@ -452,26 +452,26 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_GROUP_TEMPLATE) template = self.response_template(CREATE_GROUP_TEMPLATE)
return template.render(group=group) return template.render(group=group)
def get_group(self): def get_group(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
group = self.backend.get_group(group_name) group = self.backend.get_group(group_name)
template = self.response_template(GET_GROUP_TEMPLATE) template = self.response_template(GET_GROUP_TEMPLATE)
return template.render(group=group) return template.render(group=group)
def list_groups(self): def list_groups(self) -> str:
groups = self.backend.list_groups() groups = self.backend.list_groups()
template = self.response_template(LIST_GROUPS_TEMPLATE) template = self.response_template(LIST_GROUPS_TEMPLATE)
return template.render(groups=groups) return template.render(groups=groups)
def list_groups_for_user(self): def list_groups_for_user(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
groups = self.backend.get_groups_for_user(user_name) groups = self.backend.get_groups_for_user(user_name)
template = self.response_template(LIST_GROUPS_FOR_USER_TEMPLATE) template = self.response_template(LIST_GROUPS_FOR_USER_TEMPLATE)
return template.render(groups=groups) return template.render(groups=groups)
def put_group_policy(self): def put_group_policy(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
policy_document = self._get_param("PolicyDocument") policy_document = self._get_param("PolicyDocument")
@ -479,7 +479,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="PutGroupPolicy") return template.render(name="PutGroupPolicy")
def list_group_policies(self): def list_group_policies(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
marker = self._get_param("Marker") marker = self._get_param("Marker")
policies = self.backend.list_group_policies(group_name) policies = self.backend.list_group_policies(group_name)
@ -488,27 +488,27 @@ class IamResponse(BaseResponse):
name="ListGroupPoliciesResponse", policies=policies, marker=marker name="ListGroupPoliciesResponse", policies=policies, marker=marker
) )
def get_group_policy(self): def get_group_policy(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
policy_result = self.backend.get_group_policy(group_name, policy_name) policy_result = self.backend.get_group_policy(group_name, policy_name)
template = self.response_template(GET_GROUP_POLICY_TEMPLATE) template = self.response_template(GET_GROUP_POLICY_TEMPLATE)
return template.render(name="GetGroupPolicyResponse", **policy_result) return template.render(name="GetGroupPolicyResponse", **policy_result)
def delete_group_policy(self): def delete_group_policy(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
self.backend.delete_group_policy(group_name, policy_name) self.backend.delete_group_policy(group_name, policy_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteGroupPolicy") return template.render(name="DeleteGroupPolicy")
def delete_group(self): def delete_group(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
self.backend.delete_group(group_name) self.backend.delete_group(group_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteGroup") return template.render(name="DeleteGroup")
def update_group(self): def update_group(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
new_group_name = self._get_param("NewGroupName") new_group_name = self._get_param("NewGroupName")
new_path = self._get_param("NewPath") new_path = self._get_param("NewPath")
@ -516,7 +516,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="UpdateGroup") return template.render(name="UpdateGroup")
def create_user(self): def create_user(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
path = self._get_param("Path") path = self._get_param("Path")
tags = self._get_multi_param("Tags.member") tags = self._get_multi_param("Tags.member")
@ -524,7 +524,7 @@ class IamResponse(BaseResponse):
template = self.response_template(USER_TEMPLATE) template = self.response_template(USER_TEMPLATE)
return template.render(action="Create", user=user, tags=user_tags["Tags"]) return template.render(action="Create", user=user, tags=user_tags["Tags"])
def get_user(self): def get_user(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
if not user_name: if not user_name:
access_key_id = self.get_access_key() access_key_id = self.get_access_key()
@ -537,7 +537,7 @@ class IamResponse(BaseResponse):
template = self.response_template(USER_TEMPLATE) template = self.response_template(USER_TEMPLATE)
return template.render(action="Get", user=user, tags=tags) return template.render(action="Get", user=user, tags=tags)
def list_users(self): def list_users(self) -> str:
path_prefix = self._get_param("PathPrefix") path_prefix = self._get_param("PathPrefix")
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_param("MaxItems") max_items = self._get_param("MaxItems")
@ -545,7 +545,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_USERS_TEMPLATE) template = self.response_template(LIST_USERS_TEMPLATE)
return template.render(action="List", users=users, isTruncated=False) return template.render(action="List", users=users, isTruncated=False)
def update_user(self): def update_user(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
new_path = self._get_param("NewPath") new_path = self._get_param("NewPath")
new_user_name = self._get_param("NewUserName") new_user_name = self._get_param("NewUserName")
@ -557,7 +557,7 @@ class IamResponse(BaseResponse):
template = self.response_template(USER_TEMPLATE) template = self.response_template(USER_TEMPLATE)
return template.render(action="Update", user=user) return template.render(action="Update", user=user)
def create_login_profile(self): def create_login_profile(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
password = self._get_param("Password") password = self._get_param("Password")
user = self.backend.create_login_profile(user_name, password) user = self.backend.create_login_profile(user_name, password)
@ -565,14 +565,14 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_LOGIN_PROFILE_TEMPLATE) template = self.response_template(CREATE_LOGIN_PROFILE_TEMPLATE)
return template.render(user=user) return template.render(user=user)
def get_login_profile(self): def get_login_profile(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
user = self.backend.get_login_profile(user_name) user = self.backend.get_login_profile(user_name)
template = self.response_template(GET_LOGIN_PROFILE_TEMPLATE) template = self.response_template(GET_LOGIN_PROFILE_TEMPLATE)
return template.render(user=user) return template.render(user=user)
def update_login_profile(self): def update_login_profile(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
password = self._get_param("Password") password = self._get_param("Password")
password_reset_required = self._get_param("PasswordResetRequired") password_reset_required = self._get_param("PasswordResetRequired")
@ -583,7 +583,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_LOGIN_PROFILE_TEMPLATE) template = self.response_template(UPDATE_LOGIN_PROFILE_TEMPLATE)
return template.render(user=user) return template.render(user=user)
def add_user_to_group(self): def add_user_to_group(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
@ -591,7 +591,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="AddUserToGroup") return template.render(name="AddUserToGroup")
def remove_user_from_group(self): def remove_user_from_group(self) -> str:
group_name = self._get_param("GroupName") group_name = self._get_param("GroupName")
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
@ -599,7 +599,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="RemoveUserFromGroup") return template.render(name="RemoveUserFromGroup")
def get_user_policy(self): def get_user_policy(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
@ -611,19 +611,19 @@ class IamResponse(BaseResponse):
policy_document=policy_document.get("policy_document"), policy_document=policy_document.get("policy_document"),
) )
def list_user_policies(self): def list_user_policies(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
policies = self.backend.list_user_policies(user_name) policies = self.backend.list_user_policies(user_name)
template = self.response_template(LIST_USER_POLICIES_TEMPLATE) template = self.response_template(LIST_USER_POLICIES_TEMPLATE)
return template.render(policies=policies) return template.render(policies=policies)
def list_user_tags(self): def list_user_tags(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
tags = self.backend.list_user_tags(user_name) tags = self.backend.list_user_tags(user_name)
template = self.response_template(LIST_USER_TAGS_TEMPLATE) template = self.response_template(LIST_USER_TAGS_TEMPLATE)
return template.render(user_tags=tags["Tags"]) return template.render(user_tags=tags["Tags"])
def put_user_policy(self): def put_user_policy(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
policy_document = self._get_param("PolicyDocument") policy_document = self._get_param("PolicyDocument")
@ -632,7 +632,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="PutUserPolicy") return template.render(name="PutUserPolicy")
def delete_user_policy(self): def delete_user_policy(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
policy_name = self._get_param("PolicyName") policy_name = self._get_param("PolicyName")
@ -640,7 +640,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteUserPolicy") return template.render(name="DeleteUserPolicy")
def create_access_key(self): def create_access_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
if not user_name: if not user_name:
access_key_id = self.get_access_key() access_key_id = self.get_access_key()
@ -651,7 +651,7 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_ACCESS_KEY_TEMPLATE) template = self.response_template(CREATE_ACCESS_KEY_TEMPLATE)
return template.render(key=key) return template.render(key=key)
def update_access_key(self): def update_access_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
access_key_id = self._get_param("AccessKeyId") access_key_id = self._get_param("AccessKeyId")
status = self._get_param("Status") status = self._get_param("Status")
@ -663,7 +663,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="UpdateAccessKey") return template.render(name="UpdateAccessKey")
def get_access_key_last_used(self): def get_access_key_last_used(self) -> str:
access_key_id = self._get_param("AccessKeyId") access_key_id = self._get_param("AccessKeyId")
last_used_response = self.backend.get_access_key_last_used(access_key_id) last_used_response = self.backend.get_access_key_last_used(access_key_id)
template = self.response_template(GET_ACCESS_KEY_LAST_USED_TEMPLATE) template = self.response_template(GET_ACCESS_KEY_LAST_USED_TEMPLATE)
@ -672,7 +672,7 @@ class IamResponse(BaseResponse):
last_used=last_used_response["last_used"], last_used=last_used_response["last_used"],
) )
def list_access_keys(self): def list_access_keys(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
if not user_name: if not user_name:
access_key_id = self.get_access_key() access_key_id = self.get_access_key()
@ -683,7 +683,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_ACCESS_KEYS_TEMPLATE) template = self.response_template(LIST_ACCESS_KEYS_TEMPLATE)
return template.render(user_name=user_name, keys=keys) return template.render(user_name=user_name, keys=keys)
def delete_access_key(self): def delete_access_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
access_key_id = self._get_param("AccessKeyId") access_key_id = self._get_param("AccessKeyId")
if not user_name: if not user_name:
@ -694,7 +694,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteAccessKey") return template.render(name="DeleteAccessKey")
def upload_ssh_public_key(self): def upload_ssh_public_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
ssh_public_key_body = self._get_param("SSHPublicKeyBody") ssh_public_key_body = self._get_param("SSHPublicKeyBody")
@ -702,7 +702,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UPLOAD_SSH_PUBLIC_KEY_TEMPLATE) template = self.response_template(UPLOAD_SSH_PUBLIC_KEY_TEMPLATE)
return template.render(key=key) return template.render(key=key)
def get_ssh_public_key(self): def get_ssh_public_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
ssh_public_key_id = self._get_param("SSHPublicKeyId") ssh_public_key_id = self._get_param("SSHPublicKeyId")
@ -710,14 +710,14 @@ class IamResponse(BaseResponse):
template = self.response_template(GET_SSH_PUBLIC_KEY_TEMPLATE) template = self.response_template(GET_SSH_PUBLIC_KEY_TEMPLATE)
return template.render(key=key) return template.render(key=key)
def list_ssh_public_keys(self): def list_ssh_public_keys(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
keys = self.backend.get_all_ssh_public_keys(user_name) keys = self.backend.get_all_ssh_public_keys(user_name)
template = self.response_template(LIST_SSH_PUBLIC_KEYS_TEMPLATE) template = self.response_template(LIST_SSH_PUBLIC_KEYS_TEMPLATE)
return template.render(keys=keys) return template.render(keys=keys)
def update_ssh_public_key(self): def update_ssh_public_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
ssh_public_key_id = self._get_param("SSHPublicKeyId") ssh_public_key_id = self._get_param("SSHPublicKeyId")
status = self._get_param("Status") status = self._get_param("Status")
@ -726,7 +726,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_SSH_PUBLIC_KEY_TEMPLATE) template = self.response_template(UPDATE_SSH_PUBLIC_KEY_TEMPLATE)
return template.render() return template.render()
def delete_ssh_public_key(self): def delete_ssh_public_key(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
ssh_public_key_id = self._get_param("SSHPublicKeyId") ssh_public_key_id = self._get_param("SSHPublicKeyId")
@ -734,7 +734,7 @@ class IamResponse(BaseResponse):
template = self.response_template(DELETE_SSH_PUBLIC_KEY_TEMPLATE) template = self.response_template(DELETE_SSH_PUBLIC_KEY_TEMPLATE)
return template.render() return template.render()
def deactivate_mfa_device(self): def deactivate_mfa_device(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
serial_number = self._get_param("SerialNumber") serial_number = self._get_param("SerialNumber")
@ -742,7 +742,7 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeactivateMFADevice") return template.render(name="DeactivateMFADevice")
def enable_mfa_device(self): def enable_mfa_device(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
serial_number = self._get_param("SerialNumber") serial_number = self._get_param("SerialNumber")
authentication_code_1 = self._get_param("AuthenticationCode1") authentication_code_1 = self._get_param("AuthenticationCode1")
@ -754,13 +754,13 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="EnableMFADevice") return template.render(name="EnableMFADevice")
def list_mfa_devices(self): def list_mfa_devices(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
devices = self.backend.list_mfa_devices(user_name) devices = self.backend.list_mfa_devices(user_name)
template = self.response_template(LIST_MFA_DEVICES_TEMPLATE) template = self.response_template(LIST_MFA_DEVICES_TEMPLATE)
return template.render(user_name=user_name, devices=devices) return template.render(user_name=user_name, devices=devices)
def create_virtual_mfa_device(self): def create_virtual_mfa_device(self) -> str:
path = self._get_param("Path") path = self._get_param("Path")
virtual_mfa_device_name = self._get_param("VirtualMFADeviceName") virtual_mfa_device_name = self._get_param("VirtualMFADeviceName")
@ -771,7 +771,7 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_VIRTUAL_MFA_DEVICE_TEMPLATE) template = self.response_template(CREATE_VIRTUAL_MFA_DEVICE_TEMPLATE)
return template.render(device=virtual_mfa_device) return template.render(device=virtual_mfa_device)
def delete_virtual_mfa_device(self): def delete_virtual_mfa_device(self) -> str:
serial_number = self._get_param("SerialNumber") serial_number = self._get_param("SerialNumber")
self.backend.delete_virtual_mfa_device(serial_number) self.backend.delete_virtual_mfa_device(serial_number)
@ -779,7 +779,7 @@ class IamResponse(BaseResponse):
template = self.response_template(DELETE_VIRTUAL_MFA_DEVICE_TEMPLATE) template = self.response_template(DELETE_VIRTUAL_MFA_DEVICE_TEMPLATE)
return template.render() return template.render()
def list_virtual_mfa_devices(self): def list_virtual_mfa_devices(self) -> str:
assignment_status = self._get_param("AssignmentStatus", "Any") assignment_status = self._get_param("AssignmentStatus", "Any")
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_param("MaxItems", 100) max_items = self._get_param("MaxItems", 100)
@ -791,25 +791,25 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_VIRTUAL_MFA_DEVICES_TEMPLATE) template = self.response_template(LIST_VIRTUAL_MFA_DEVICES_TEMPLATE)
return template.render(devices=devices, marker=marker) return template.render(devices=devices, marker=marker)
def delete_user(self): def delete_user(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
self.backend.delete_user(user_name) self.backend.delete_user(user_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteUser") return template.render(name="DeleteUser")
def delete_policy(self): def delete_policy(self) -> str:
policy_arn = self._get_param("PolicyArn") policy_arn = self._get_param("PolicyArn")
self.backend.delete_policy(policy_arn) self.backend.delete_policy(policy_arn)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeletePolicy") return template.render(name="DeletePolicy")
def delete_login_profile(self): def delete_login_profile(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
self.backend.delete_login_profile(user_name) self.backend.delete_login_profile(user_name)
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteLoginProfile") return template.render(name="DeleteLoginProfile")
def generate_credential_report(self): def generate_credential_report(self) -> str:
if self.backend.report_generated(): if self.backend.report_generated():
template = self.response_template(CREDENTIAL_REPORT_GENERATED) template = self.response_template(CREDENTIAL_REPORT_GENERATED)
else: else:
@ -817,28 +817,28 @@ class IamResponse(BaseResponse):
self.backend.generate_report() self.backend.generate_report()
return template.render() return template.render()
def get_credential_report(self): def get_credential_report(self) -> str:
report = self.backend.get_credential_report() report = self.backend.get_credential_report()
template = self.response_template(CREDENTIAL_REPORT) template = self.response_template(CREDENTIAL_REPORT)
return template.render(report=report) return template.render(report=report)
def list_account_aliases(self): def list_account_aliases(self) -> str:
aliases = self.backend.list_account_aliases() aliases = self.backend.list_account_aliases()
template = self.response_template(LIST_ACCOUNT_ALIASES_TEMPLATE) template = self.response_template(LIST_ACCOUNT_ALIASES_TEMPLATE)
return template.render(aliases=aliases) return template.render(aliases=aliases)
def create_account_alias(self): def create_account_alias(self) -> str:
alias = self._get_param("AccountAlias") alias = self._get_param("AccountAlias")
self.backend.create_account_alias(alias) self.backend.create_account_alias(alias)
template = self.response_template(CREATE_ACCOUNT_ALIAS_TEMPLATE) template = self.response_template(CREATE_ACCOUNT_ALIAS_TEMPLATE)
return template.render() return template.render()
def delete_account_alias(self): def delete_account_alias(self) -> str:
self.backend.delete_account_alias() self.backend.delete_account_alias()
template = self.response_template(DELETE_ACCOUNT_ALIAS_TEMPLATE) template = self.response_template(DELETE_ACCOUNT_ALIAS_TEMPLATE)
return template.render() return template.render()
def get_account_authorization_details(self): def get_account_authorization_details(self) -> str:
filter_param = self._get_multi_param("Filter.member") filter_param = self._get_multi_param("Filter.member")
account_details = self.backend.get_account_authorization_details(filter_param) account_details = self.backend.get_account_authorization_details(filter_param)
template = self.response_template(GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE) template = self.response_template(GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE)
@ -852,7 +852,7 @@ class IamResponse(BaseResponse):
list_tags_for_user=self.backend.list_user_tags, list_tags_for_user=self.backend.list_user_tags,
) )
def create_saml_provider(self): def create_saml_provider(self) -> str:
saml_provider_name = self._get_param("Name") saml_provider_name = self._get_param("Name")
saml_metadata_document = self._get_param("SAMLMetadataDocument") saml_metadata_document = self._get_param("SAMLMetadataDocument")
saml_provider = self.backend.create_saml_provider( saml_provider = self.backend.create_saml_provider(
@ -862,7 +862,7 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_SAML_PROVIDER_TEMPLATE) template = self.response_template(CREATE_SAML_PROVIDER_TEMPLATE)
return template.render(saml_provider=saml_provider) return template.render(saml_provider=saml_provider)
def update_saml_provider(self): def update_saml_provider(self) -> str:
saml_provider_arn = self._get_param("SAMLProviderArn") saml_provider_arn = self._get_param("SAMLProviderArn")
saml_metadata_document = self._get_param("SAMLMetadataDocument") saml_metadata_document = self._get_param("SAMLMetadataDocument")
saml_provider = self.backend.update_saml_provider( saml_provider = self.backend.update_saml_provider(
@ -872,27 +872,27 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_SAML_PROVIDER_TEMPLATE) template = self.response_template(UPDATE_SAML_PROVIDER_TEMPLATE)
return template.render(saml_provider=saml_provider) return template.render(saml_provider=saml_provider)
def delete_saml_provider(self): def delete_saml_provider(self) -> str:
saml_provider_arn = self._get_param("SAMLProviderArn") saml_provider_arn = self._get_param("SAMLProviderArn")
self.backend.delete_saml_provider(saml_provider_arn) self.backend.delete_saml_provider(saml_provider_arn)
template = self.response_template(DELETE_SAML_PROVIDER_TEMPLATE) template = self.response_template(DELETE_SAML_PROVIDER_TEMPLATE)
return template.render() return template.render()
def list_saml_providers(self): def list_saml_providers(self) -> str:
saml_providers = self.backend.list_saml_providers() saml_providers = self.backend.list_saml_providers()
template = self.response_template(LIST_SAML_PROVIDERS_TEMPLATE) template = self.response_template(LIST_SAML_PROVIDERS_TEMPLATE)
return template.render(saml_providers=saml_providers) return template.render(saml_providers=saml_providers)
def get_saml_provider(self): def get_saml_provider(self) -> str:
saml_provider_arn = self._get_param("SAMLProviderArn") saml_provider_arn = self._get_param("SAMLProviderArn")
saml_provider = self.backend.get_saml_provider(saml_provider_arn) saml_provider = self.backend.get_saml_provider(saml_provider_arn)
template = self.response_template(GET_SAML_PROVIDER_TEMPLATE) template = self.response_template(GET_SAML_PROVIDER_TEMPLATE)
return template.render(saml_provider=saml_provider) return template.render(saml_provider=saml_provider)
def upload_signing_certificate(self): def upload_signing_certificate(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
cert_body = self._get_param("CertificateBody") cert_body = self._get_param("CertificateBody")
@ -900,7 +900,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UPLOAD_SIGNING_CERTIFICATE_TEMPLATE) template = self.response_template(UPLOAD_SIGNING_CERTIFICATE_TEMPLATE)
return template.render(cert=cert) return template.render(cert=cert)
def update_signing_certificate(self): def update_signing_certificate(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
cert_id = self._get_param("CertificateId") cert_id = self._get_param("CertificateId")
status = self._get_param("Status") status = self._get_param("Status")
@ -909,7 +909,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_SIGNING_CERTIFICATE_TEMPLATE) template = self.response_template(UPDATE_SIGNING_CERTIFICATE_TEMPLATE)
return template.render() return template.render()
def delete_signing_certificate(self): def delete_signing_certificate(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
cert_id = self._get_param("CertificateId") cert_id = self._get_param("CertificateId")
@ -917,14 +917,14 @@ class IamResponse(BaseResponse):
template = self.response_template(DELETE_SIGNING_CERTIFICATE_TEMPLATE) template = self.response_template(DELETE_SIGNING_CERTIFICATE_TEMPLATE)
return template.render() return template.render()
def list_signing_certificates(self): def list_signing_certificates(self) -> str:
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
certs = self.backend.list_signing_certificates(user_name) certs = self.backend.list_signing_certificates(user_name)
template = self.response_template(LIST_SIGNING_CERTIFICATES_TEMPLATE) template = self.response_template(LIST_SIGNING_CERTIFICATES_TEMPLATE)
return template.render(user_name=user_name, certificates=certs) return template.render(user_name=user_name, certificates=certs)
def list_role_tags(self): def list_role_tags(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_param("MaxItems", 100) max_items = self._get_param("MaxItems", 100)
@ -934,7 +934,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_ROLE_TAG_TEMPLATE) template = self.response_template(LIST_ROLE_TAG_TEMPLATE)
return template.render(tags=tags, marker=marker) return template.render(tags=tags, marker=marker)
def tag_role(self): def tag_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
tags = self._get_multi_param("Tags.member") tags = self._get_multi_param("Tags.member")
@ -943,7 +943,7 @@ class IamResponse(BaseResponse):
template = self.response_template(TAG_ROLE_TEMPLATE) template = self.response_template(TAG_ROLE_TEMPLATE)
return template.render() return template.render()
def untag_role(self): def untag_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
tag_keys = self._get_multi_param("TagKeys.member") tag_keys = self._get_multi_param("TagKeys.member")
@ -952,7 +952,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UNTAG_ROLE_TEMPLATE) template = self.response_template(UNTAG_ROLE_TEMPLATE)
return template.render() return template.render()
def create_open_id_connect_provider(self): def create_open_id_connect_provider(self) -> str:
open_id_provider_url = self._get_param("Url") open_id_provider_url = self._get_param("Url")
thumbprint_list = self._get_multi_param("ThumbprintList.member") thumbprint_list = self._get_multi_param("ThumbprintList.member")
client_id_list = self._get_multi_param("ClientIDList.member") client_id_list = self._get_multi_param("ClientIDList.member")
@ -965,7 +965,7 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE) template = self.response_template(CREATE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE)
return template.render(open_id_provider=open_id_provider) return template.render(open_id_provider=open_id_provider)
def update_open_id_connect_provider_thumbprint(self): def update_open_id_connect_provider_thumbprint(self) -> str:
open_id_provider_arn = self._get_param("OpenIDConnectProviderArn") open_id_provider_arn = self._get_param("OpenIDConnectProviderArn")
thumbprint_list = self._get_multi_param("ThumbprintList.member") thumbprint_list = self._get_multi_param("ThumbprintList.member")
@ -976,7 +976,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_OPEN_ID_CONNECT_PROVIDER_THUMBPRINT) template = self.response_template(UPDATE_OPEN_ID_CONNECT_PROVIDER_THUMBPRINT)
return template.render() return template.render()
def tag_open_id_connect_provider(self): def tag_open_id_connect_provider(self) -> str:
open_id_provider_arn = self._get_param("OpenIDConnectProviderArn") open_id_provider_arn = self._get_param("OpenIDConnectProviderArn")
tags = self._get_multi_param("Tags.member") tags = self._get_multi_param("Tags.member")
@ -985,7 +985,7 @@ class IamResponse(BaseResponse):
template = self.response_template(TAG_OPEN_ID_CONNECT_PROVIDER) template = self.response_template(TAG_OPEN_ID_CONNECT_PROVIDER)
return template.render() return template.render()
def untag_open_id_connect_provider(self): def untag_open_id_connect_provider(self) -> str:
open_id_provider_arn = self._get_param("OpenIDConnectProviderArn") open_id_provider_arn = self._get_param("OpenIDConnectProviderArn")
tag_keys = self._get_multi_param("TagKeys.member") tag_keys = self._get_multi_param("TagKeys.member")
@ -994,7 +994,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UNTAG_OPEN_ID_CONNECT_PROVIDER) template = self.response_template(UNTAG_OPEN_ID_CONNECT_PROVIDER)
return template.render() return template.render()
def list_open_id_connect_provider_tags(self): def list_open_id_connect_provider_tags(self) -> str:
open_id_provider_arn = self._get_param("OpenIDConnectProviderArn") open_id_provider_arn = self._get_param("OpenIDConnectProviderArn")
marker = self._get_param("Marker") marker = self._get_param("Marker")
max_items = self._get_param("MaxItems", 100) max_items = self._get_param("MaxItems", 100)
@ -1004,7 +1004,7 @@ class IamResponse(BaseResponse):
template = self.response_template(LIST_OPEN_ID_CONNECT_PROVIDER_TAGS) template = self.response_template(LIST_OPEN_ID_CONNECT_PROVIDER_TAGS)
return template.render(tags=tags, marker=marker) return template.render(tags=tags, marker=marker)
def delete_open_id_connect_provider(self): def delete_open_id_connect_provider(self) -> str:
open_id_provider_arn = self._get_param("OpenIDConnectProviderArn") open_id_provider_arn = self._get_param("OpenIDConnectProviderArn")
self.backend.delete_open_id_connect_provider(open_id_provider_arn) self.backend.delete_open_id_connect_provider(open_id_provider_arn)
@ -1012,7 +1012,7 @@ class IamResponse(BaseResponse):
template = self.response_template(DELETE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE) template = self.response_template(DELETE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE)
return template.render() return template.render()
def get_open_id_connect_provider(self): def get_open_id_connect_provider(self) -> str:
open_id_provider_arn = self._get_param("OpenIDConnectProviderArn") open_id_provider_arn = self._get_param("OpenIDConnectProviderArn")
open_id_provider = self.backend.get_open_id_connect_provider( open_id_provider = self.backend.get_open_id_connect_provider(
@ -1022,13 +1022,13 @@ class IamResponse(BaseResponse):
template = self.response_template(GET_OPEN_ID_CONNECT_PROVIDER_TEMPLATE) template = self.response_template(GET_OPEN_ID_CONNECT_PROVIDER_TEMPLATE)
return template.render(open_id_provider=open_id_provider) return template.render(open_id_provider=open_id_provider)
def list_open_id_connect_providers(self): def list_open_id_connect_providers(self) -> str:
open_id_provider_arns = self.backend.list_open_id_connect_providers() open_id_provider_arns = self.backend.list_open_id_connect_providers()
template = self.response_template(LIST_OPEN_ID_CONNECT_PROVIDERS_TEMPLATE) template = self.response_template(LIST_OPEN_ID_CONNECT_PROVIDERS_TEMPLATE)
return template.render(open_id_provider_arns=open_id_provider_arns) return template.render(open_id_provider_arns=open_id_provider_arns)
def update_account_password_policy(self): def update_account_password_policy(self) -> str:
allow_change_password = self._get_bool_param( allow_change_password = self._get_bool_param(
"AllowUsersToChangePassword", False "AllowUsersToChangePassword", False
) )
@ -1060,25 +1060,25 @@ class IamResponse(BaseResponse):
template = self.response_template(UPDATE_ACCOUNT_PASSWORD_POLICY_TEMPLATE) template = self.response_template(UPDATE_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
return template.render() return template.render()
def get_account_password_policy(self): def get_account_password_policy(self) -> str:
account_password_policy = self.backend.get_account_password_policy() account_password_policy = self.backend.get_account_password_policy()
template = self.response_template(GET_ACCOUNT_PASSWORD_POLICY_TEMPLATE) template = self.response_template(GET_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
return template.render(password_policy=account_password_policy) return template.render(password_policy=account_password_policy)
def delete_account_password_policy(self): def delete_account_password_policy(self) -> str:
self.backend.delete_account_password_policy() self.backend.delete_account_password_policy()
template = self.response_template(DELETE_ACCOUNT_PASSWORD_POLICY_TEMPLATE) template = self.response_template(DELETE_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
return template.render() return template.render()
def get_account_summary(self): def get_account_summary(self) -> str:
account_summary = self.backend.get_account_summary() account_summary = self.backend.get_account_summary()
template = self.response_template(GET_ACCOUNT_SUMMARY_TEMPLATE) template = self.response_template(GET_ACCOUNT_SUMMARY_TEMPLATE)
return template.render(summary_map=account_summary.summary_map) return template.render(summary_map=account_summary.summary_map)
def tag_user(self): def tag_user(self) -> str:
name = self._get_param("UserName") name = self._get_param("UserName")
tags = self._get_multi_param("Tags.member") tags = self._get_multi_param("Tags.member")
@ -1087,7 +1087,7 @@ class IamResponse(BaseResponse):
template = self.response_template(TAG_USER_TEMPLATE) template = self.response_template(TAG_USER_TEMPLATE)
return template.render() return template.render()
def untag_user(self): def untag_user(self) -> str:
name = self._get_param("UserName") name = self._get_param("UserName")
tag_keys = self._get_multi_param("TagKeys.member") tag_keys = self._get_multi_param("TagKeys.member")
@ -1096,7 +1096,7 @@ class IamResponse(BaseResponse):
template = self.response_template(UNTAG_USER_TEMPLATE) template = self.response_template(UNTAG_USER_TEMPLATE)
return template.render() return template.render()
def create_service_linked_role(self): def create_service_linked_role(self) -> str:
service_name = self._get_param("AWSServiceName") service_name = self._get_param("AWSServiceName")
description = self._get_param("Description") description = self._get_param("Description")
suffix = self._get_param("CustomSuffix") suffix = self._get_param("CustomSuffix")
@ -1108,7 +1108,7 @@ class IamResponse(BaseResponse):
template = self.response_template(CREATE_SERVICE_LINKED_ROLE_TEMPLATE) template = self.response_template(CREATE_SERVICE_LINKED_ROLE_TEMPLATE)
return template.render(role=role) return template.render(role=role)
def delete_service_linked_role(self): def delete_service_linked_role(self) -> str:
role_name = self._get_param("RoleName") role_name = self._get_param("RoleName")
deletion_task_id = self.backend.delete_service_linked_role(role_name) deletion_task_id = self.backend.delete_service_linked_role(role_name)
@ -1116,7 +1116,7 @@ class IamResponse(BaseResponse):
template = self.response_template(DELETE_SERVICE_LINKED_ROLE_TEMPLATE) template = self.response_template(DELETE_SERVICE_LINKED_ROLE_TEMPLATE)
return template.render(deletion_task_id=deletion_task_id) return template.render(deletion_task_id=deletion_task_id)
def get_service_linked_role_deletion_status(self): def get_service_linked_role_deletion_status(self) -> str:
self.backend.get_service_linked_role_deletion_status() self.backend.get_service_linked_role_deletion_status()
template = self.response_template( template = self.response_template(

View File

@ -6,13 +6,13 @@ AWS_ROLE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
ACCOUNT_OFFSET = 549755813888 # int.from_bytes(base64.b32decode(b"QAAAAAAA"), byteorder="big"), start value ACCOUNT_OFFSET = 549755813888 # int.from_bytes(base64.b32decode(b"QAAAAAAA"), byteorder="big"), start value
def _random_uppercase_or_digit_sequence(length): def _random_uppercase_or_digit_sequence(length: int) -> str:
return "".join(str(random.choice(AWS_ROLE_ALPHABET)) for _ in range(length)) return "".join(str(random.choice(AWS_ROLE_ALPHABET)) for _ in range(length))
def generate_access_key_id_from_account_id( def generate_access_key_id_from_account_id(
account_id: str, prefix: str, total_length: int = 20 account_id: str, prefix: str, total_length: int = 20
): ) -> str:
""" """
Generates a key id (e.g. access key id) for the given account id and prefix Generates a key id (e.g. access key id) for the given account id and prefix
@ -21,13 +21,13 @@ def generate_access_key_id_from_account_id(
:param total_length: Total length of the access key (e.g. 20 for temp access keys, 21 for role ids) :param total_length: Total length of the access key (e.g. 20 for temp access keys, 21 for role ids)
:return: Generated id :return: Generated id
""" """
account_id = int(account_id) account_id_nr = int(account_id)
id_with_offset = account_id // 2 + ACCOUNT_OFFSET id_with_offset = account_id_nr // 2 + ACCOUNT_OFFSET
account_bytes = int.to_bytes(id_with_offset, byteorder="big", length=5) account_bytes = int.to_bytes(id_with_offset, byteorder="big", length=5)
account_part = base64.b32encode(account_bytes).decode("utf-8") account_part = base64.b32encode(account_bytes).decode("utf-8")
middle_char = ( middle_char = (
random.choice(AWS_ROLE_ALPHABET[16:]) random.choice(AWS_ROLE_ALPHABET[16:])
if account_id % 2 if account_id_nr % 2
else random.choice(AWS_ROLE_ALPHABET[:16]) else random.choice(AWS_ROLE_ALPHABET[:16])
) )
semi_fixed_part = prefix + account_part + middle_char semi_fixed_part = prefix + account_part + middle_char
@ -36,14 +36,14 @@ def generate_access_key_id_from_account_id(
) )
def random_alphanumeric(length): def random_alphanumeric(length: int) -> str:
return "".join( return "".join(
str(random.choice(string.ascii_letters + string.digits + "+" + "/")) str(random.choice(string.ascii_letters + string.digits + "+" + "/"))
for _ in range(length) for _ in range(length)
) )
def random_resource_id(size=20): def random_resource_id(size: int = 20) -> str:
chars = list(range(10)) + list(string.ascii_lowercase) chars = list(range(10)) + list(string.ascii_lowercase)
return "".join(str(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))
@ -55,13 +55,13 @@ def random_role_id(account_id: str) -> str:
) )
def random_access_key(): def random_access_key() -> str:
return "".join( return "".join(
str(random.choice(string.ascii_uppercase + string.digits)) for _ in range(16) str(random.choice(string.ascii_uppercase + string.digits)) for _ in range(16)
) )
def random_policy_id(): def random_policy_id() -> str:
return "A" + "".join( return "A" + "".join(
random.choice(string.ascii_uppercase + string.digits) for _ in range(20) random.choice(string.ascii_uppercase + string.digits) for _ in range(20)
) )

View File

@ -55,12 +55,12 @@ class InvalidArgumentError(S3ClientError):
class AccessForbidden(S3ClientError): class AccessForbidden(S3ClientError):
code = 403 code = 403
def __init__(self, msg): def __init__(self, msg: str):
super().__init__("AccessForbidden", msg) super().__init__("AccessForbidden", msg)
class BucketError(S3ClientError): class BucketError(S3ClientError):
def __init__(self, *args, **kwargs): def __init__(self, *args: str, **kwargs: str):
kwargs.setdefault("template", "bucket_error") kwargs.setdefault("template", "bucket_error")
self.templates["bucket_error"] = ERROR_WITH_BUCKET_NAME self.templates["bucket_error"] = ERROR_WITH_BUCKET_NAME
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -335,45 +335,40 @@ class DuplicateTagKeys(S3ClientError):
class S3AccessDeniedError(S3ClientError): class S3AccessDeniedError(S3ClientError):
code = 403 code = 403
def __init__(self, *args, **kwargs): def __init__(self, *args: str, **kwargs: str):
super().__init__("AccessDenied", "Access Denied", *args, **kwargs) super().__init__("AccessDenied", "Access Denied", *args, **kwargs)
class BucketAccessDeniedError(BucketError): class BucketAccessDeniedError(BucketError):
code = 403 code = 403
def __init__(self, *args, **kwargs): def __init__(self, *args: str, **kwargs: str):
super().__init__("AccessDenied", "Access Denied", *args, **kwargs) super().__init__("AccessDenied", "Access Denied", *args, **kwargs)
class S3InvalidTokenError(S3ClientError): class S3InvalidTokenError(S3ClientError):
code = 400 code = 400
def __init__(self, *args, **kwargs): def __init__(self) -> None:
super().__init__( super().__init__(
"InvalidToken", "InvalidToken", "The provided token is malformed or otherwise invalid."
"The provided token is malformed or otherwise invalid.",
*args,
**kwargs,
) )
class S3AclAndGrantError(S3ClientError): class S3AclAndGrantError(S3ClientError):
code = 400 code = 400
def __init__(self, *args, **kwargs): def __init__(self) -> None:
super().__init__( super().__init__(
"InvalidRequest", "InvalidRequest",
"Specifying both Canned ACLs and Header Grants is not allowed", "Specifying both Canned ACLs and Header Grants is not allowed",
*args,
**kwargs,
) )
class BucketInvalidTokenError(BucketError): class BucketInvalidTokenError(BucketError):
code = 400 code = 400
def __init__(self, *args, **kwargs): def __init__(self, *args: str, **kwargs: str):
super().__init__( super().__init__(
"InvalidToken", "InvalidToken",
"The provided token is malformed or otherwise invalid.", "The provided token is malformed or otherwise invalid.",
@ -385,19 +380,17 @@ class BucketInvalidTokenError(BucketError):
class S3InvalidAccessKeyIdError(S3ClientError): class S3InvalidAccessKeyIdError(S3ClientError):
code = 403 code = 403
def __init__(self, *args, **kwargs): def __init__(self) -> None:
super().__init__( super().__init__(
"InvalidAccessKeyId", "InvalidAccessKeyId",
"The AWS Access Key Id you provided does not exist in our records.", "The AWS Access Key Id you provided does not exist in our records.",
*args,
**kwargs,
) )
class BucketInvalidAccessKeyIdError(S3ClientError): class BucketInvalidAccessKeyIdError(S3ClientError):
code = 403 code = 403
def __init__(self, *args, **kwargs): def __init__(self, *args: str, **kwargs: str):
super().__init__( super().__init__(
"InvalidAccessKeyId", "InvalidAccessKeyId",
"The AWS Access Key Id you provided does not exist in our records.", "The AWS Access Key Id you provided does not exist in our records.",
@ -409,19 +402,17 @@ class BucketInvalidAccessKeyIdError(S3ClientError):
class S3SignatureDoesNotMatchError(S3ClientError): class S3SignatureDoesNotMatchError(S3ClientError):
code = 403 code = 403
def __init__(self, *args, **kwargs): def __init__(self) -> None:
super().__init__( super().__init__(
"SignatureDoesNotMatch", "SignatureDoesNotMatch",
"The request signature we calculated does not match the signature you provided. Check your key and signing method.", "The request signature we calculated does not match the signature you provided. Check your key and signing method.",
*args,
**kwargs,
) )
class BucketSignatureDoesNotMatchError(S3ClientError): class BucketSignatureDoesNotMatchError(S3ClientError):
code = 403 code = 403
def __init__(self, *args, **kwargs): def __init__(self, *args: str, **kwargs: str):
super().__init__( super().__init__(
"SignatureDoesNotMatch", "SignatureDoesNotMatch",
"The request signature we calculated does not match the signature you provided. Check your key and signing method.", "The request signature we calculated does not match the signature you provided. Check your key and signing method.",

View File

@ -10,7 +10,6 @@ from moto.sts.utils import (
DEFAULT_STS_SESSION_DURATION, DEFAULT_STS_SESSION_DURATION,
random_assumed_role_id, random_assumed_role_id,
) )
from typing import Mapping
class Token(BaseModel): class Token(BaseModel):
@ -185,6 +184,6 @@ class STSBackend(BaseBackend):
return account_id, iam_backend.create_temp_access_key() return account_id, iam_backend.create_temp_access_key()
sts_backends: Mapping[str, STSBackend] = BackendDict( sts_backends = BackendDict(
STSBackend, "sts", use_boto3_regions=False, additional_regions=["global"] STSBackend, "sts", use_boto3_regions=False, additional_regions=["global"]
) )

View File

@ -230,7 +230,7 @@ disable = W,C,R,E
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
[mypy] [mypy]
files= moto/a*,moto/b*,moto/c*,moto/d*,moto/e*,moto/f*,moto/g*,moto/moto_api,moto/neptune files= moto/a*,moto/b*,moto/c*,moto/d*,moto/e*,moto/f*,moto/g*,moto/iam,moto/moto_api,moto/neptune
show_column_numbers=True show_column_numbers=True
show_error_codes = True show_error_codes = True
disable_error_code=abstract disable_error_code=abstract