Interfaces for IAM in S3 client #199
4 changed files with 1039 additions and 17 deletions
|
@ -29,13 +29,17 @@ class AwsCliClient(S3ClientWrapper):
|
||||||
|
|
||||||
@reporter.step("Configure S3 client (aws cli)")
|
@reporter.step("Configure S3 client (aws cli)")
|
||||||
def __init__(
|
def __init__(
|
||||||
self, access_key_id: str, secret_access_key: str, s3gate_endpoint: str, profile: str = "default"
|
self, access_key_id: str, secret_access_key: str, s3gate_endpoint: str, profile: str = "default", region: str = "us-east-1"
|
||||||
|
|||||||
) -> None:
|
) -> None:
|
||||||
self.s3gate_endpoint = s3gate_endpoint
|
self.s3gate_endpoint = s3gate_endpoint
|
||||||
|
self.access_key_id: str = access_key_id
|
||||||
|
self.secret_access_key: str = secret_access_key
|
||||||
self.profile = profile
|
self.profile = profile
|
||||||
self.local_shell = LocalShell()
|
self.local_shell = LocalShell()
|
||||||
|
self.region = region
|
||||||
|
self.iam_endpoint = None
|
||||||
try:
|
try:
|
||||||
_configure_aws_cli(f"aws configure --profile {profile}", access_key_id, secret_access_key)
|
_configure_aws_cli(f"aws configure --profile {profile}", access_key_id, secret_access_key, region)
|
||||||
self.local_shell.exec(f"aws configure set max_attempts {MAX_REQUEST_ATTEMPTS} --profile {profile}")
|
self.local_shell.exec(f"aws configure set max_attempts {MAX_REQUEST_ATTEMPTS} --profile {profile}")
|
||||||
self.local_shell.exec(
|
self.local_shell.exec(
|
||||||
f"aws configure set retry_mode {RETRY_MODE} --profile {profile}",
|
f"aws configure set retry_mode {RETRY_MODE} --profile {profile}",
|
||||||
|
@ -43,10 +47,14 @@ class AwsCliClient(S3ClientWrapper):
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
raise RuntimeError("Error while configuring AwsCliClient") from err
|
raise RuntimeError("Error while configuring AwsCliClient") from err
|
||||||
|
|
||||||
@reporter.step("Set endpoint S3 to {s3gate_endpoint}")
|
@reporter.step("Set S3 endpoint to {s3gate_endpoint}")
|
||||||
def set_endpoint(self, s3gate_endpoint: str):
|
def set_endpoint(self, s3gate_endpoint: str):
|
||||||
self.s3gate_endpoint = s3gate_endpoint
|
self.s3gate_endpoint = s3gate_endpoint
|
||||||
|
|
||||||
|
@reporter.step("Set IAM endpoint to {iam_endpoint}")
|
||||||
|
def set_iam_endpoint(self, iam_endpoint: str):
|
||||||
|
self.iam_endpoint = iam_endpoint
|
||||||
|
|
||||||
@reporter.step("Create bucket S3")
|
@reporter.step("Create bucket S3")
|
||||||
def create_bucket(
|
def create_bucket(
|
||||||
self,
|
self,
|
||||||
|
@ -565,12 +573,13 @@ class AwsCliClient(S3ClientWrapper):
|
||||||
self.local_shell.exec(cmd)
|
self.local_shell.exec(cmd)
|
||||||
|
|
||||||
@reporter.step("Put object tagging")
|
@reporter.step("Put object tagging")
|
||||||
def put_object_tagging(self, bucket: str, key: str, tags: list) -> None:
|
def put_object_tagging(self, bucket: str, key: str, tags: list, version_id: Optional[str] = '') -> None:
|
||||||
tags = [{"Key": tag_key, "Value": tag_value} for tag_key, tag_value in tags]
|
tags = [{"Key": tag_key, "Value": tag_value} for tag_key, tag_value in tags]
|
||||||
tagging = {"TagSet": tags}
|
tagging = {"TagSet": tags}
|
||||||
|
version = f" --version-id {version_id}" if version_id else ""
|
||||||
cmd = (
|
cmd = (
|
||||||
f"aws {self.common_flags} s3api put-object-tagging --bucket {bucket} --key {key} "
|
f"aws {self.common_flags} s3api put-object-tagging --bucket {bucket} --key {key} "
|
||||||
f"--tagging '{json.dumps(tagging)}' --endpoint {self.s3gate_endpoint} --profile {self.profile}"
|
f"{version} --tagging '{json.dumps(tagging)}' --endpoint {self.s3gate_endpoint} --profile {self.profile}"
|
||||||
)
|
)
|
||||||
self.local_shell.exec(cmd)
|
self.local_shell.exec(cmd)
|
||||||
|
|
||||||
|
@ -586,10 +595,11 @@ class AwsCliClient(S3ClientWrapper):
|
||||||
return response.get("TagSet")
|
return response.get("TagSet")
|
||||||
|
|
||||||
@reporter.step("Delete object tagging")
|
@reporter.step("Delete object tagging")
|
||||||
def delete_object_tagging(self, bucket: str, key: str) -> None:
|
def delete_object_tagging(self, bucket: str, key: str, version_id: Optional[str] = None) -> None:
|
||||||
|
version = f" --version-id {version_id}" if version_id else ""
|
||||||
cmd = (
|
cmd = (
|
||||||
f"aws {self.common_flags} s3api delete-object-tagging --bucket {bucket} "
|
f"aws {self.common_flags} s3api delete-object-tagging --bucket {bucket} "
|
||||||
f"--key {key} --endpoint {self.s3gate_endpoint} --profile {self.profile}"
|
f"--key {key} {version} --endpoint {self.s3gate_endpoint} --profile {self.profile}"
|
||||||
)
|
)
|
||||||
self.local_shell.exec(cmd)
|
self.local_shell.exec(cmd)
|
||||||
|
|
||||||
|
@ -750,3 +760,563 @@ class AwsCliClient(S3ClientWrapper):
|
||||||
json_output = json.loads(output[output.index("{") :])
|
json_output = json.loads(output[output.index("{") :])
|
||||||
|
|
||||||
return json_output
|
return json_output
|
||||||
|
|
||||||
|
# IAM METHODS #
|
||||||
|
# Some methods don't have checks because AWS is silent in some cases (delete, attach, etc.)
|
||||||
|
|
||||||
|
@reporter.step("Adds the specified user to the specified group")
|
||||||
|
def iam_add_user_to_group(self, user_name: str, group_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam add-user-to-group --user-name {user_name} --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Attaches the specified managed policy to the specified IAM group")
|
||||||
|
def iam_attach_group_policy(self, group_name: str, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam attach-group-policy --group-name {group_name} --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Attaches the specified managed policy to the specified user")
|
||||||
|
def iam_attach_user_policy(self, user_name: str, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam attach-user-policy --user-name {user_name} --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new AWS secret access key and access key ID for the specified user")
|
||||||
|
def iam_create_access_key(self, user_name: Optional[str] = None) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam create-access-key --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
if user_name:
|
||||||
|
cmd += f" --user-name {user_name}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
access_key_id = response["AccessKey"].get("AccessKeyId")
|
||||||
|
secret_access_key = response["AccessKey"].get("SecretAccessKey")
|
||||||
|
assert access_key_id, f"Expected AccessKeyId in response:\n{response}"
|
||||||
|
assert secret_access_key, f"Expected SecretAccessKey in response:\n{response}"
|
||||||
|
|
||||||
|
return access_key_id, secret_access_key
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new group")
|
||||||
|
def iam_create_group(self, group_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam create-group --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("Group"), f"Expected Group in response:\n{response}"
|
||||||
|
assert response["Group"].get("GroupName") == group_name, f"GroupName should be equal to {group_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new managed policy for your AWS account")
|
||||||
|
def iam_create_policy(self, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam create-policy --endpoint {self.iam_endpoint}"
|
||||||
|
f" --policy-name {policy_name} --policy-document '{json.dumps(policy_document)}'"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("Policy"), f"Expected Policy in response:\n{response}"
|
||||||
|
assert response["Policy"].get("PolicyName") == policy_name, f"PolicyName should be equal to {policy_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new IAM user for your AWS account")
|
||||||
|
def iam_create_user(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam create-user --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("User"), f"Expected User in response:\n{response}"
|
||||||
|
assert response["User"].get("UserName") == user_name, f"UserName should be equal to {user_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the access key pair associated with the specified IAM user")
|
||||||
|
def iam_delete_access_key(self, access_key_id: str, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam delete-access-key --access-key-id {access_key_id} --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified IAM group")
|
||||||
|
def iam_delete_group(self, group_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam delete-group --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified inline policy that is embedded in the specified IAM group")
|
||||||
|
def iam_delete_group_policy(self, group_name: str, policy_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam delete-group-policy --group-name {group_name} --policy-name {policy_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified managed policy")
|
||||||
|
def iam_delete_policy(self, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam delete-policy --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified IAM user")
|
||||||
|
def iam_delete_user(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam delete-user --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified inline policy that is embedded in the specified IAM user")
|
||||||
|
def iam_delete_user_policy(self, user_name: str, policy_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam delete-user-policy --user-name {user_name} --policy-name {policy_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Removes the specified managed policy from the specified IAM group")
|
||||||
|
def iam_detach_group_policy(self, group_name: str, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam detach-group-policy --group-name {group_name} --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Removes the specified managed policy from the specified user")
|
||||||
|
def iam_detach_user_policy(self, user_name: str, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam detach-user-policy --user-name {user_name} --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Returns a list of IAM users that are in the specified IAM group")
|
||||||
|
def iam_get_group(self, group_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam get-group --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert "Users" in response.keys(), f"Expected Users in response:\n{response}"
|
||||||
|
assert response.get("Group").get("GroupName") == group_name, f"GroupName should be equal to {group_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves the specified inline policy document that is embedded in the specified IAM group")
|
||||||
|
def iam_get_group_policy(self, group_name: str, policy_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam get-group-policy --group-name {group_name} --policy-name {policy_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves information about the specified managed policy")
|
||||||
|
def iam_get_policy(self, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam get-policy --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("Policy"), f"Expected Policy in response:\n{response}"
|
||||||
|
assert response["Policy"].get("PolicyName") == policy_name, f"PolicyName should be equal to {policy_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves information about the specified version of the specified managed policy")
|
||||||
|
def iam_get_policy_version(self, policy_arn: str, version_id: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam get-policy-version --policy-arn {policy_arn} --version-id {version_id} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("PolicyVersion"), f"Expected PolicyVersion in response:\n{response}"
|
||||||
|
assert response["PolicyVersion"].get("VersionId") == version_id, f"VersionId should be equal to {version_id}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves information about the specified IAM user")
|
||||||
|
def iam_get_user(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam get-user --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("User"), f"Expected User in response:\n{response}"
|
||||||
|
assert response["User"].get("UserName") == user_name, f"UserName should be equal to {user_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves the specified inline policy document that is embedded in the specified IAM user")
|
||||||
|
def iam_get_user_policy(self, user_name: str, policy_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam get-user-policy --user-name {user_name} --policy-name {policy_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("UserName"), f"Expected User in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Returns information about the access key IDs associated with the specified IAM user")
|
||||||
|
def iam_list_access_keys(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-access-keys --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all managed policies that are attached to the specified IAM group")
|
||||||
|
def iam_list_attached_group_policies(self, group_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-attached-group-policies --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("AttachedPolicies"), f"Expected AttachedPolicies in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all managed policies that are attached to the specified IAM user")
|
||||||
|
def iam_list_attached_user_policies(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-attached-user-policies --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("AttachedPolicies"), f"Expected AttachedPolicies in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all IAM users, groups, and roles that the specified managed policy is attached to")
|
||||||
|
def iam_list_entities_for_policy(self, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-entities-for-policy --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("PolicyGroups"), f"Expected PolicyGroups in response:\n{response}"
|
||||||
|
assert response.get("PolicyUsers"), f"Expected PolicyUsers in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the names of the inline policies that are embedded in the specified IAM group")
|
||||||
|
def iam_list_group_policies(self, group_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-group-policies --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("PolicyNames"), f"Expected PolicyNames in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the IAM groups")
|
||||||
|
def iam_list_groups(self) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-groups --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("Groups"), f"Expected Groups in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the IAM groups that the specified IAM user belongs to")
|
||||||
|
def iam_list_groups_for_user(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-groups-for-user --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("Groups"), f"Expected Groups in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all the managed policies that are available in your AWS account")
|
||||||
|
def iam_list_policies(self) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-policies --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert 'Policies' in response.keys(), f"Expected Policies in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists information about the versions of the specified managed policy")
|
||||||
|
def iam_list_policy_versions(self, policy_arn: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-policy-versions --policy-arn {policy_arn} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("Versions"), f"Expected Versions in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the names of the inline policies embedded in the specified IAM user")
|
||||||
|
def iam_list_user_policies(self, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-user-policies --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert response.get("PolicyNames"), f"Expected PolicyNames in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the IAM users")
|
||||||
|
def iam_list_users(self) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam list-users --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
assert "Users" in response.keys(), f"Expected Users in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Adds or updates an inline policy document that is embedded in the specified IAM group")
|
||||||
|
def iam_put_group_policy(self, group_name: str, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam put-group-policy --endpoint {self.iam_endpoint}"
|
||||||
|
f" --group-name {group_name} --policy-name {policy_name} --policy-document \'{json.dumps(policy_document)}\'"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Adds or updates an inline policy document that is embedded in the specified IAM user")
|
||||||
|
def iam_put_user_policy(self, user_name: str, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam put-user-policy --endpoint {self.iam_endpoint}"
|
||||||
|
f" --user-name {user_name} --policy-name {policy_name} --policy-document \'{json.dumps(policy_document)}\'"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Removes the specified user from the specified group")
|
||||||
|
def iam_remove_user_from_group(self, group_name: str, user_name: str) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam remove-user-from-group --endpoint {self.iam_endpoint}"
|
||||||
|
f" --group-name {group_name} --user-name {user_name}"
|
||||||
|
)
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Updates the name and/or the path of the specified IAM group")
|
||||||
|
def iam_update_group(self, group_name: str, new_name: Optional[str] = None, new_path: Optional[str] = None) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam update-group --group-name {group_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if new_name:
|
||||||
|
cmd += f" --new-group-name {new_name}"
|
||||||
|
if new_path:
|
||||||
|
cmd += f" --new-path {new_path}"
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Updates the name and/or the path of the specified IAM user")
|
||||||
|
def iam_update_user(self, user_name: str, new_name: Optional[str] = None, new_path: Optional[str] = None) -> dict:
|
||||||
|
cmd = (
|
||||||
|
f"aws {self.common_flags} iam update-user --user-name {user_name} --endpoint {self.iam_endpoint}"
|
||||||
|
)
|
||||||
|
if new_name:
|
||||||
|
cmd += f" --new-user-name {new_name}"
|
||||||
|
if new_path:
|
||||||
|
cmd += f" --new-path {new_path}"
|
||||||
|
if self.profile:
|
||||||
|
cmd += f" --profile {self.profile}"
|
||||||
|
|
||||||
|
output = self.local_shell.exec(cmd).stdout
|
||||||
|
response = self._to_json(output)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ from frostfs_testlib.resources.common import ASSETS_DIR, MAX_REQUEST_ATTEMPTS, R
|
||||||
from frostfs_testlib.s3.interfaces import S3ClientWrapper, VersioningStatus, _make_objs_dict
|
from frostfs_testlib.s3.interfaces import S3ClientWrapper, VersioningStatus, _make_objs_dict
|
||||||
from frostfs_testlib.utils.cli_utils import log_command_execution
|
from frostfs_testlib.utils.cli_utils import log_command_execution
|
||||||
|
|
||||||
|
# TODO: Refactor this code to use shell instead of _cmd_run
|
||||||
|
from frostfs_testlib.utils.cli_utils import _configure_aws_cli
|
||||||
|
|
||||||
logger = logging.getLogger("NeoLogger")
|
logger = logging.getLogger("NeoLogger")
|
||||||
|
|
||||||
# Disable warnings on self-signed certificate which the
|
# Disable warnings on self-signed certificate which the
|
||||||
|
@ -43,10 +46,11 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
@reporter.step("Configure S3 client (boto3)")
|
@reporter.step("Configure S3 client (boto3)")
|
||||||
@report_error
|
@report_error
|
||||||
def __init__(
|
def __init__(
|
||||||
self, access_key_id: str, secret_access_key: str, s3gate_endpoint: str, profile: str = "default"
|
self, access_key_id: str, secret_access_key: str, s3gate_endpoint: str, profile: str = "default", region: str = "us-east-1"
|
||||||
) -> None:
|
) -> None:
|
||||||
self.boto3_client: S3Client = None
|
self.boto3_client: S3Client = None
|
||||||
self.session = boto3.Session()
|
self.session = boto3.Session()
|
||||||
|
self.region = region
|
||||||
self.config = Config(
|
self.config = Config(
|
||||||
retries={
|
retries={
|
||||||
"max_attempts": MAX_REQUEST_ATTEMPTS,
|
"max_attempts": MAX_REQUEST_ATTEMPTS,
|
||||||
|
@ -56,6 +60,7 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
self.access_key_id: str = access_key_id
|
self.access_key_id: str = access_key_id
|
||||||
self.secret_access_key: str = secret_access_key
|
self.secret_access_key: str = secret_access_key
|
||||||
self.s3gate_endpoint: str = ""
|
self.s3gate_endpoint: str = ""
|
||||||
|
self.boto3_iam_client: S3Client = None
|
||||||
self.set_endpoint(s3gate_endpoint)
|
self.set_endpoint(s3gate_endpoint)
|
||||||
|
|
||||||
@reporter.step("Set endpoint S3 to {s3gate_endpoint}")
|
@reporter.step("Set endpoint S3 to {s3gate_endpoint}")
|
||||||
|
@ -69,11 +74,23 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
service_name="s3",
|
service_name="s3",
|
||||||
aws_access_key_id=self.access_key_id,
|
aws_access_key_id=self.access_key_id,
|
||||||
aws_secret_access_key=self.secret_access_key,
|
aws_secret_access_key=self.secret_access_key,
|
||||||
|
region_name=self.region,
|
||||||
config=self.config,
|
config=self.config,
|
||||||
endpoint_url=s3gate_endpoint,
|
endpoint_url=s3gate_endpoint,
|
||||||
verify=False,
|
verify=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Set endpoint IAM to {iam_endpoint}")
|
||||||
|
def set_iam_endpoint(self, iam_endpoint: str):
|
||||||
|
self.boto3_iam_client = self.session.client(
|
||||||
|
service_name="iam",
|
||||||
|
aws_access_key_id=self.access_key_id,
|
||||||
|
aws_secret_access_key=self.secret_access_key,
|
||||||
|
endpoint_url=iam_endpoint,
|
||||||
|
verify=False,)
|
||||||
|
|
||||||
|
|
||||||
def _to_s3_param(self, param: str):
|
def _to_s3_param(self, param: str):
|
||||||
replacement_map = {
|
replacement_map = {
|
||||||
"Acl": "ACL",
|
"Acl": "ACL",
|
||||||
|
@ -118,7 +135,7 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
|
|
||||||
s3_bucket = self.boto3_client.create_bucket(**params)
|
s3_bucket = self.boto3_client.create_bucket(**params)
|
||||||
log_command_execution(f"Created S3 bucket {bucket}", s3_bucket)
|
log_command_execution(f"Created S3 bucket {bucket}", s3_bucket)
|
||||||
sleep(S3_SYNC_WAIT_TIME)
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
return bucket
|
return bucket
|
||||||
|
|
||||||
@reporter.step("List buckets S3")
|
@reporter.step("List buckets S3")
|
||||||
|
@ -139,7 +156,7 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
def delete_bucket(self, bucket: str) -> None:
|
def delete_bucket(self, bucket: str) -> None:
|
||||||
response = self.boto3_client.delete_bucket(Bucket=bucket)
|
response = self.boto3_client.delete_bucket(Bucket=bucket)
|
||||||
log_command_execution("S3 Delete bucket result", response)
|
log_command_execution("S3 Delete bucket result", response)
|
||||||
sleep(S3_SYNC_WAIT_TIME)
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
|
||||||
@reporter.step("Head bucket S3")
|
@reporter.step("Head bucket S3")
|
||||||
@report_error
|
@report_error
|
||||||
|
@ -355,7 +372,7 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
}
|
}
|
||||||
response = self.boto3_client.delete_object(**params)
|
response = self.boto3_client.delete_object(**params)
|
||||||
log_command_execution("S3 Delete object result", response)
|
log_command_execution("S3 Delete object result", response)
|
||||||
sleep(S3_SYNC_WAIT_TIME)
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@reporter.step("Delete objects S3")
|
@reporter.step("Delete objects S3")
|
||||||
|
@ -366,7 +383,7 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
assert (
|
assert (
|
||||||
"Errors" not in response
|
"Errors" not in response
|
||||||
), f'The following objects have not been deleted: {[err_info["Key"] for err_info in response["Errors"]]}.\nError Message: {response["Errors"]["Message"]}'
|
), f'The following objects have not been deleted: {[err_info["Key"] for err_info in response["Errors"]]}.\nError Message: {response["Errors"]["Message"]}'
|
||||||
sleep(S3_SYNC_WAIT_TIME)
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@reporter.step("Delete object versions S3")
|
@reporter.step("Delete object versions S3")
|
||||||
|
@ -592,10 +609,10 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
|
|
||||||
@reporter.step("Put object tagging")
|
@reporter.step("Put object tagging")
|
||||||
@report_error
|
@report_error
|
||||||
def put_object_tagging(self, bucket: str, key: str, tags: list) -> None:
|
def put_object_tagging(self, bucket: str, key: str, tags: list, version_id: Optional[str] = '') -> None:
|
||||||
tags = [{"Key": tag_key, "Value": tag_value} for tag_key, tag_value in tags]
|
tags = [{"Key": tag_key, "Value": tag_value} for tag_key, tag_value in tags]
|
||||||
tagging = {"TagSet": tags}
|
tagging = {"TagSet": tags}
|
||||||
response = self.boto3_client.put_object_tagging(Bucket=bucket, Key=key, Tagging=tagging)
|
response = self.boto3_client.put_object_tagging(Bucket=bucket, Key=key, Tagging=tagging, VersionId=version_id)
|
||||||
log_command_execution("S3 Put object tagging", response)
|
log_command_execution("S3 Put object tagging", response)
|
||||||
|
|
||||||
@reporter.step("Get object tagging")
|
@reporter.step("Get object tagging")
|
||||||
|
@ -654,3 +671,287 @@ class Boto3ClientWrapper(S3ClientWrapper):
|
||||||
raise NotImplementedError("Cp is not supported for boto3 client")
|
raise NotImplementedError("Cp is not supported for boto3 client")
|
||||||
|
|
||||||
# END OBJECT METHODS #
|
# END OBJECT METHODS #
|
||||||
|
|
||||||
|
|
||||||
|
# IAM METHODS #
|
||||||
|
# Some methods don't have checks because boto3 is silent in some cases (delete, attach, etc.)
|
||||||
|
|
||||||
|
@reporter.step("Adds the specified user to the specified group")
|
||||||
|
def iam_add_user_to_group(self, user_name: str, group_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.add_user_to_group(UserName=user_name, GroupName=group_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Attaches the specified managed policy to the specified IAM group")
|
||||||
|
def iam_attach_group_policy(self, group_name: str, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.attach_group_policy(GroupName=group_name, PolicyArn=policy_arn)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Attaches the specified managed policy to the specified user")
|
||||||
|
def iam_attach_user_policy(self, user_name: str, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.attach_user_policy(UserName=user_name, PolicyArn=policy_arn)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new AWS secret access key and access key ID for the specified user")
|
||||||
|
def iam_create_access_key(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.create_access_key(UserName=user_name)
|
||||||
|
|
||||||
|
access_key_id = response["AccessKey"].get("AccessKeyId")
|
||||||
|
secret_access_key = response["AccessKey"].get("SecretAccessKey")
|
||||||
|
assert access_key_id, f"Expected AccessKeyId in response:\n{response}"
|
||||||
|
assert secret_access_key, f"Expected SecretAccessKey in response:\n{response}"
|
||||||
|
|
||||||
|
return access_key_id, secret_access_key
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new group")
|
||||||
|
def iam_create_group(self, group_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.create_group(GroupName=group_name)
|
||||||
|
assert response.get("Group"), f"Expected Group in response:\n{response}"
|
||||||
|
assert response["Group"].get("GroupName") == group_name, f"GroupName should be equal to {group_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new managed policy for your AWS account")
|
||||||
|
def iam_create_policy(self, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
response = self.boto3_iam_client.create_policy(PolicyName=policy_name, PolicyDocument=json.dumps(policy_document))
|
||||||
|
assert response.get("Policy"), f"Expected Policy in response:\n{response}"
|
||||||
|
assert response["Policy"].get("PolicyName") == policy_name, f"PolicyName should be equal to {policy_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Creates a new IAM user for your AWS account")
|
||||||
|
def iam_create_user(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.create_user(UserName=user_name)
|
||||||
|
assert response.get("User"), f"Expected User in response:\n{response}"
|
||||||
|
assert response["User"].get("UserName") == user_name, f"UserName should be equal to {user_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the access key pair associated with the specified IAM user")
|
||||||
|
def iam_delete_access_key(self, access_key_id: str, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.delete_access_key(AccessKeyId=access_key_id, UserName=user_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified IAM group")
|
||||||
|
def iam_delete_group(self, group_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.delete_group(GroupName=group_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified inline policy that is embedded in the specified IAM group")
|
||||||
|
def iam_delete_group_policy(self, group_name: str, policy_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.delete_group_policy(GroupName=group_name, PolicyName=policy_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified managed policy")
|
||||||
|
def iam_delete_policy(self, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.delete_policy(PolicyArn=policy_arn)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified IAM user")
|
||||||
|
def iam_delete_user(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.delete_user(UserName=user_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Deletes the specified inline policy that is embedded in the specified IAM user")
|
||||||
|
def iam_delete_user_policy(self, user_name: str, policy_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.delete_user_policy(UserName=user_name, PolicyName=policy_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Removes the specified managed policy from the specified IAM group")
|
||||||
|
def iam_detach_group_policy(self, group_name: str, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.detach_group_policy(GroupName=group_name, PolicyArn=policy_arn)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Removes the specified managed policy from the specified user")
|
||||||
|
def iam_detach_user_policy(self, user_name: str, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.detach_user_policy(UserName=user_name, PolicyArn=policy_arn)
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Returns a list of IAM users that are in the specified IAM group")
|
||||||
|
def iam_get_group(self, group_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.get_group(GroupName=group_name)
|
||||||
|
assert response.get("Group").get("GroupName") == group_name, f"GroupName should be equal to {group_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves the specified inline policy document that is embedded in the specified IAM group")
|
||||||
|
def iam_get_group_policy(self, group_name: str, policy_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.get_group_policy(GroupName=group_name, PolicyName=policy_name)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves information about the specified managed policy")
|
||||||
|
def iam_get_policy(self, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.get_policy(PolicyArn=policy_arn)
|
||||||
|
assert response.get("Policy"), f"Expected Policy in response:\n{response}"
|
||||||
|
assert response["Policy"].get("PolicyName") == policy_name, f"PolicyName should be equal to {policy_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves information about the specified version of the specified managed policy")
|
||||||
|
def iam_get_policy_version(self, policy_arn: str, version_id: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.get_policy_version(PolicyArn=policy_arn, VersionId=version_id)
|
||||||
|
assert response.get("PolicyVersion"), f"Expected PolicyVersion in response:\n{response}"
|
||||||
|
assert response["PolicyVersion"].get("VersionId") == version_id, f"VersionId should be equal to {version_id}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves information about the specified IAM user")
|
||||||
|
def iam_get_user(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.get_user(UserName=user_name)
|
||||||
|
assert response.get("User"), f"Expected User in response:\n{response}"
|
||||||
|
assert response["User"].get("UserName") == user_name, f"UserName should be equal to {user_name}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Retrieves the specified inline policy document that is embedded in the specified IAM user")
|
||||||
|
def iam_get_user_policy(self, user_name: str, policy_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.get_user_policy(UserName=user_name, PolicyName=policy_name)
|
||||||
|
assert response.get("UserName"), f"Expected UserName in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Returns information about the access key IDs associated with the specified IAM user")
|
||||||
|
def iam_list_access_keys(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_access_keys(UserName=user_name)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all managed policies that are attached to the specified IAM group")
|
||||||
|
def iam_list_attached_group_policies(self, group_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_attached_group_policies(GroupName=group_name)
|
||||||
|
assert response.get("AttachedPolicies"), f"Expected AttachedPolicies in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all managed policies that are attached to the specified IAM user")
|
||||||
|
def iam_list_attached_user_policies(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_attached_user_policies(UserName=user_name)
|
||||||
|
assert response.get("AttachedPolicies"), f"Expected AttachedPolicies in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all IAM users, groups, and roles that the specified managed policy is attached to")
|
||||||
|
def iam_list_entities_for_policy(self, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_entities_for_policy(PolicyArn=policy_arn)
|
||||||
|
|
||||||
|
assert response.get("PolicyGroups"), f"Expected PolicyGroups in response:\n{response}"
|
||||||
|
assert response.get("PolicyUsers"), f"Expected PolicyUsers in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the names of the inline policies that are embedded in the specified IAM group")
|
||||||
|
def iam_list_group_policies(self, group_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_group_policies(GroupName=group_name)
|
||||||
|
assert response.get("PolicyNames"), f"Expected PolicyNames in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the IAM groups")
|
||||||
|
def iam_list_groups(self) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_groups()
|
||||||
|
assert response.get("Groups"), f"Expected Groups in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the IAM groups that the specified IAM user belongs to")
|
||||||
|
def iam_list_groups_for_user(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_groups_for_user(UserName=user_name)
|
||||||
|
assert response.get("Groups"), f"Expected Groups in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists all the managed policies that are available in your AWS account")
|
||||||
|
def iam_list_policies(self) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_policies()
|
||||||
|
assert response.get("Policies"), f"Expected Policies in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists information about the versions of the specified managed policy")
|
||||||
|
def iam_list_policy_versions(self, policy_arn: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_policy_versions(PolicyArn=policy_arn)
|
||||||
|
assert response.get("Versions"), f"Expected Versions in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the names of the inline policies embedded in the specified IAM user")
|
||||||
|
def iam_list_user_policies(self, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_user_policies(UserName=user_name)
|
||||||
|
assert response.get("PolicyNames"), f"Expected PolicyNames in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Lists the IAM users")
|
||||||
|
def iam_list_users(self) -> dict:
|
||||||
|
response = self.boto3_iam_client.list_users()
|
||||||
|
assert response.get("Users"), f"Expected Users in response:\n{response}"
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Adds or updates an inline policy document that is embedded in the specified IAM group")
|
||||||
|
def iam_put_group_policy(self, group_name: str, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
response = self.boto3_iam_client.put_group_policy(GroupName=group_name, PolicyName=policy_name, PolicyDocument=json.dumps(policy_document))
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Adds or updates an inline policy document that is embedded in the specified IAM user")
|
||||||
|
def iam_put_user_policy(self, user_name: str, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
response = self.boto3_iam_client.put_user_policy(UserName=user_name, PolicyName=policy_name, PolicyDocument=json.dumps(policy_document))
|
||||||
|
sleep(S3_SYNC_WAIT_TIME * 10)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Removes the specified user from the specified group")
|
||||||
|
def iam_remove_user_from_group(self, group_name: str, user_name: str) -> dict:
|
||||||
|
response = self.boto3_iam_client.remove_user_from_group(GroupName=group_name, UserName=user_name)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Updates the name and/or the path of the specified IAM group")
|
||||||
|
def iam_update_group(self, group_name: str, new_name: str, new_path: Optional[str] = None) -> dict:
|
||||||
|
response = self.boto3_iam_client.update_group(GroupName=group_name, NewGroupName=new_name, NewPath='/')
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@reporter.step("Updates the name and/or the path of the specified IAM user")
|
||||||
|
def iam_update_user(self, user_name: str, new_name: str, new_path: Optional[str] = None) -> dict:
|
||||||
|
response = self.boto3_iam_client.update_user(UserName=user_name, NewUserName=new_name, NewPath='/')
|
||||||
|
return response
|
|
@ -50,7 +50,7 @@ class BucketContainerResolver(ABC):
|
||||||
|
|
||||||
class S3ClientWrapper(HumanReadableABC):
|
class S3ClientWrapper(HumanReadableABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self, access_key_id: str, secret_access_key: str, s3gate_endpoint: str, profile: str) -> None:
|
def __init__(self, access_key_id: str, secret_access_key: str, s3gate_endpoint: str, profile: str, region: str) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -395,3 +395,154 @@ class S3ClientWrapper(HumanReadableABC):
|
||||||
"""cp directory TODO: Add proper description"""
|
"""cp directory TODO: Add proper description"""
|
||||||
|
|
||||||
# END OF OBJECT METHODS #
|
# END OF OBJECT METHODS #
|
||||||
|
|
||||||
|
|
||||||
|
# IAM METHODS #
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_add_user_to_group(self, user_name: str, group_name: str) -> dict:
|
||||||
|
'''Adds the specified user to the specified group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_attach_group_policy(self, group: str, policy_arn: str) -> dict:
|
||||||
|
'''Attaches the specified managed policy to the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_attach_user_policy(self, user_name: str, policy_arn: str) -> dict:
|
||||||
|
'''Attaches the specified managed policy to the specified user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_create_access_key(self, user_name: str) -> dict:
|
||||||
|
'''Creates a new AWS secret access key and access key ID for the specified user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_create_group(self, group_name: str) -> dict:
|
||||||
|
'''Creates a new group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_create_policy(self, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
'''Creates a new managed policy for your AWS account'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_create_user(self, user_name: str) -> dict:
|
||||||
|
'''Creates a new IAM user for your AWS account'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_delete_access_key(self, access_key_id: str, user_name: str) -> dict:
|
||||||
|
'''Deletes the access key pair associated with the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_delete_group(self, group_name: str) -> dict:
|
||||||
|
'''Deletes the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_delete_group_policy(self, group_name: str, policy_name: str) -> dict:
|
||||||
|
'''Deletes the specified inline policy that is embedded in the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_delete_policy(self, policy_arn: str) -> dict:
|
||||||
|
'''Deletes the specified managed policy'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_delete_user(self, user_name: str) -> dict:
|
||||||
|
'''Deletes the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_delete_user_policy(self, user_name: str, policy_name: str) -> dict:
|
||||||
|
'''Deletes the specified inline policy that is embedded in the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_detach_group_policy(self, group_name: str, policy_arn: str) -> dict:
|
||||||
|
'''Removes the specified managed policy from the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_detach_user_policy(self, user_name: str, policy_arn: str) -> dict:
|
||||||
|
'''Removes the specified managed policy from the specified user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_get_group(self, group_name: str) -> dict:
|
||||||
|
'''Returns a list of IAM users that are in the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_get_group_policy(self, group_name: str, policy_name: str) -> dict:
|
||||||
|
'''Retrieves the specified inline policy document that is embedded in the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_get_policy(self, policy_arn: str) -> dict:
|
||||||
|
'''Retrieves information about the specified managed policy'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_get_policy_version(self, policy_arn: str, version_id: str) -> dict:
|
||||||
|
'''Retrieves information about the specified version of the specified managed policy'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_get_user(self, user_name: str) -> dict:
|
||||||
|
'''Retrieves information about the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_get_user_policy(self, user_name: str, policy_name: str) -> dict:
|
||||||
|
'''Retrieves the specified inline policy document that is embedded in the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_access_keys(self, user_name: str) -> dict:
|
||||||
|
'''Returns information about the access key IDs associated with the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_attached_group_policies(self, group_name: str) -> dict:
|
||||||
|
'''Lists all managed policies that are attached to the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_attached_user_policies(self, user_name: str) -> dict:
|
||||||
|
'''Lists all managed policies that are attached to the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_entities_for_policy(self, policy_arn: str) -> dict:
|
||||||
|
'''Lists all IAM users, groups, and roles that the specified managed policy is attached to'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_group_policies(self, group_name: str) -> dict:
|
||||||
|
'''Lists the names of the inline policies that are embedded in the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_groups(self) -> dict:
|
||||||
|
'''Lists the IAM groups'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_groups_for_user(self, user_name: str) -> dict:
|
||||||
|
'''Lists the IAM groups that the specified IAM user belongs to'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_policies(self) -> dict:
|
||||||
|
'''Lists all the managed policies that are available in your AWS account'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_policy_versions(self, policy_arn: str) -> dict:
|
||||||
|
'''Lists information about the versions of the specified managed policy'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_user_policies(self, user_name: str) -> dict:
|
||||||
|
'''Lists the names of the inline policies embedded in the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_list_users(self) -> dict:
|
||||||
|
'''Lists the IAM users'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_put_group_policy(self, group_name: str, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
'''Adds or updates an inline policy document that is embedded in the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_put_user_policy(self, user_name: str, policy_name: str, policy_document: dict) -> dict:
|
||||||
|
'''Adds or updates an inline policy document that is embedded in the specified IAM user'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_remove_user_from_group(self, group_name: str, user_name: str) -> dict:
|
||||||
|
'''Removes the specified user from the specified group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_update_group(self, group_name: str, new_name: Optional[str] = None, new_path: Optional[str] = None) -> dict:
|
||||||
|
'''Updates the name and/or the path of the specified IAM group'''
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def iam_update_user(self, user_name: str, new_name: Optional[str] = None, new_path: Optional[str] = None) -> dict:
|
||||||
|
'''Updates the name and/or the path of the specified IAM user'''
|
||||||
|
|
|
@ -41,7 +41,7 @@ def _run_with_passwd(cmd: str) -> str:
|
||||||
return cmd.decode()
|
return cmd.decode()
|
||||||
|
|
||||||
|
|
||||||
def _configure_aws_cli(cmd: str, key_id: str, access_key: str, out_format: str = "json") -> str:
|
def _configure_aws_cli(cmd: str, key_id: str, access_key: str, region: str, out_format: str = "json") -> str:
|
||||||
child = pexpect.spawn(cmd)
|
child = pexpect.spawn(cmd)
|
||||||
child.delaybeforesend = 1
|
child.delaybeforesend = 1
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ def _configure_aws_cli(cmd: str, key_id: str, access_key: str, out_format: str =
|
||||||
child.sendline(access_key)
|
child.sendline(access_key)
|
||||||
|
|
||||||
child.expect("Default region name.*")
|
child.expect("Default region name.*")
|
||||||
child.sendline("")
|
child.sendline("region")
|
||||||
|
|
||||||
child.expect("Default output format.*")
|
child.expect("Default output format.*")
|
||||||
child.sendline(out_format)
|
child.sendline(out_format)
|
||||||
|
|
Loading…
Reference in a new issue
__init__
is an abstract method which comes fromS3ClientWrapper
For consistency, we need to also modify init for
S3ClientWrapper
interface andBoto3ClientWrapper
class