IAM validation: Now supports SSM requests (#6785)
This commit is contained in:
parent
3545d38595
commit
ca9d8fc420
@ -149,6 +149,7 @@ class ActionAuthenticatorMixin(object):
|
|||||||
method=self.method, # type: ignore[attr-defined]
|
method=self.method, # type: ignore[attr-defined]
|
||||||
path=path,
|
path=path,
|
||||||
data=self.data, # type: ignore[attr-defined]
|
data=self.data, # type: ignore[attr-defined]
|
||||||
|
body=self.body, # type: ignore[attr-defined]
|
||||||
headers=self.headers, # type: ignore[attr-defined]
|
headers=self.headers, # type: ignore[attr-defined]
|
||||||
)
|
)
|
||||||
iam_request.check_signature()
|
iam_request.check_signature()
|
||||||
|
@ -174,6 +174,7 @@ class IAMRequestBase(object, metaclass=ABCMeta):
|
|||||||
method: str,
|
method: str,
|
||||||
path: str,
|
path: str,
|
||||||
data: Dict[str, str],
|
data: Dict[str, str],
|
||||||
|
body: bytes,
|
||||||
headers: Dict[str, str],
|
headers: Dict[str, str],
|
||||||
):
|
):
|
||||||
log.debug(
|
log.debug(
|
||||||
@ -183,6 +184,7 @@ class IAMRequestBase(object, metaclass=ABCMeta):
|
|||||||
self._method = method
|
self._method = method
|
||||||
self._path = path
|
self._path = path
|
||||||
self._data = data
|
self._data = data
|
||||||
|
self._body = body
|
||||||
self._headers = headers
|
self._headers = headers
|
||||||
credential_scope = self._get_string_between(
|
credential_scope = self._get_string_between(
|
||||||
"Credential=", ",", self._headers["Authorization"]
|
"Credential=", ",", self._headers["Authorization"]
|
||||||
@ -190,13 +192,14 @@ class IAMRequestBase(object, metaclass=ABCMeta):
|
|||||||
credential_data = credential_scope.split("/")
|
credential_data = credential_scope.split("/")
|
||||||
self._region = credential_data[2]
|
self._region = credential_data[2]
|
||||||
self._service = credential_data[3]
|
self._service = credential_data[3]
|
||||||
|
action_from_request = self._action_from_request()
|
||||||
self._action = (
|
self._action = (
|
||||||
self._service
|
self._service
|
||||||
+ ":"
|
+ ":"
|
||||||
+ (
|
+ (
|
||||||
self._data["Action"][0]
|
action_from_request[0]
|
||||||
if isinstance(self._data["Action"], list)
|
if isinstance(action_from_request, list)
|
||||||
else self._data["Action"]
|
else action_from_request
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
@ -208,6 +211,11 @@ 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 _action_from_request(self) -> str:
|
||||||
|
if "X-Amz-Target" in self._headers:
|
||||||
|
return self._headers["X-Amz-Target"].split(".")[-1]
|
||||||
|
return self._data["Action"]
|
||||||
|
|
||||||
def check_signature(self) -> None:
|
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"]
|
||||||
@ -267,7 +275,10 @@ class IAMRequestBase(object, metaclass=ABCMeta):
|
|||||||
).split(";")
|
).split(";")
|
||||||
headers = self._create_headers_for_aws_request(signed_headers, self._headers)
|
headers = self._create_headers_for_aws_request(signed_headers, self._headers)
|
||||||
request = AWSRequest(
|
request = AWSRequest(
|
||||||
method=self._method, url=self._path, data=self._data, headers=headers
|
method=self._method,
|
||||||
|
url=self._path,
|
||||||
|
data=self._body or self._data,
|
||||||
|
headers=headers,
|
||||||
)
|
)
|
||||||
request.context["timestamp"] = headers["X-Amz-Date"]
|
request.context["timestamp"] = headers["X-Amz-Date"]
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from botocore.exceptions import ClientError
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from moto import mock_iam, mock_ec2, mock_s3, mock_sts, mock_elbv2, mock_rds
|
from moto import mock_iam, mock_ec2, mock_s3, mock_sts, mock_ssm, mock_elbv2, mock_rds
|
||||||
from moto.core import set_initial_no_auth_action_count
|
from moto.core import set_initial_no_auth_action_count
|
||||||
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
|
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
@ -831,3 +831,30 @@ def test_allow_key_access_using_resource_arn() -> None:
|
|||||||
s3_client.put_object(Bucket="my_bucket", Key="keyname", Body=b"test")
|
s3_client.put_object(Bucket="my_bucket", Key="keyname", Body=b"test")
|
||||||
with pytest.raises(ClientError):
|
with pytest.raises(ClientError):
|
||||||
s3_client.put_object(Bucket="my_bucket", Key="unknown", Body=b"test")
|
s3_client.put_object(Bucket="my_bucket", Key="unknown", Body=b"test")
|
||||||
|
|
||||||
|
|
||||||
|
@set_initial_no_auth_action_count(3)
|
||||||
|
@mock_ssm
|
||||||
|
@mock_iam
|
||||||
|
def test_ssm_service():
|
||||||
|
user_name = "test-user"
|
||||||
|
policy_doc = {
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Action": ["ssm:*"],
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Resource": ["*"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
access_key = create_user_with_access_key_and_inline_policy(user_name, policy_doc)
|
||||||
|
|
||||||
|
ssmc = boto3.client(
|
||||||
|
"ssm",
|
||||||
|
region_name="us-east-1",
|
||||||
|
aws_access_key_id=access_key["AccessKeyId"],
|
||||||
|
aws_secret_access_key=access_key["SecretAccessKey"],
|
||||||
|
)
|
||||||
|
|
||||||
|
ssmc.put_parameter(Name="test", Value="value", Type="String")
|
||||||
|
Loading…
Reference in New Issue
Block a user