481 lines
16 KiB
Python
481 lines
16 KiB
Python
import json
|
|
|
|
import boto3
|
|
import pytest
|
|
from botocore.exceptions import ClientError
|
|
|
|
from moto import mock_aws
|
|
from moto.iam.aws_managed_policies import aws_managed_policies_data
|
|
|
|
# See our Development Tips on writing tests for hints on how to write good tests:
|
|
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
|
|
|
|
DUMMY_PERMISSIONSET_ID = (
|
|
"arn:aws:sso:::permissionSet/ins-eeeeffffgggghhhh/ps-hhhhkkkkppppoooo"
|
|
)
|
|
DUMMY_INSTANCE_ARN = "arn:aws:sso:::instance/ins-aaaabbbbccccdddd"
|
|
|
|
|
|
@pytest.fixture(name="managed_policies")
|
|
def get_managed_policies():
|
|
return json.loads(aws_managed_policies_data)
|
|
|
|
|
|
def create_permissionset(client) -> str:
|
|
"""Helper function to create a dummy permission set and returns the arn."""
|
|
|
|
response = client.create_permission_set(
|
|
Name="test-permission-set",
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
Description="test permission set",
|
|
)
|
|
|
|
return response["PermissionSet"]["PermissionSetArn"]
|
|
|
|
|
|
@mock_aws
|
|
def test_put_inline_policy_to_permission_set():
|
|
"""
|
|
Tests putting and getting an inline policy to a permission set.
|
|
"""
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
|
|
permission_set_arn = create_permissionset(client)
|
|
dummy_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": "s3:GetObject",
|
|
"Resource": "arn:aws:s3:::your-bucket-name/*",
|
|
}
|
|
],
|
|
}
|
|
|
|
# Happy path
|
|
response = client.put_inline_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
InlinePolicy=json.dumps(dummy_policy),
|
|
)
|
|
|
|
response = client.get_inline_policy_for_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert response["InlinePolicy"] == json.dumps(dummy_policy)
|
|
|
|
# Invalid permission set arn
|
|
not_create_ps_arn = (
|
|
"arn:aws:sso:::permissionSet/ins-eeeeffffgggghhhh/ps-hhhhkkkkppppoxyz"
|
|
)
|
|
with pytest.raises(ClientError) as e:
|
|
client.put_inline_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=not_create_ps_arn,
|
|
InlinePolicy=json.dumps(dummy_policy),
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ResourceNotFoundException"
|
|
assert err["Message"] == "Could not find PermissionSet with id ps-hhhhkkkkppppoxyz"
|
|
|
|
|
|
@mock_aws
|
|
def test_get_inline_policy_to_permission_set_no_policy():
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
|
|
permission_set_arn = create_permissionset(client)
|
|
|
|
response = client.get_inline_policy_for_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert response["InlinePolicy"] == ""
|
|
|
|
|
|
@mock_aws
|
|
def test_delete_inline_policy_to_permissionset():
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
|
|
permission_set_arn = create_permissionset(client)
|
|
|
|
dummy_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": "s3:GetObject",
|
|
"Resource": "arn:aws:s3:::your-bucket-name/*",
|
|
}
|
|
],
|
|
}
|
|
|
|
client.put_inline_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
InlinePolicy=json.dumps(dummy_policy),
|
|
)
|
|
|
|
response = client.get_inline_policy_for_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert response["InlinePolicy"] == json.dumps(dummy_policy)
|
|
|
|
client.delete_inline_policy_from_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
response = client.get_inline_policy_for_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert response["InlinePolicy"] == ""
|
|
|
|
|
|
@mock_aws
|
|
def test_attach_managed_policy_to_permission_set():
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
|
|
permission_set_arn = create_permissionset(client)
|
|
permissionset_id = permission_set_arn.split("/")[-1]
|
|
managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
|
|
|
|
client.attach_managed_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=managed_policy_arn,
|
|
)
|
|
|
|
response = client.list_managed_policies_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert response["AttachedManagedPolicies"][0]["Name"] == "AdministratorAccess"
|
|
assert (
|
|
response["AttachedManagedPolicies"][0]["Arn"]
|
|
== "arn:aws:iam::aws:policy/AdministratorAccess"
|
|
)
|
|
|
|
# test for managed policy that is already attached
|
|
with pytest.raises(ClientError) as e:
|
|
client.attach_managed_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=managed_policy_arn,
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ConflictException"
|
|
assert (
|
|
err["Message"]
|
|
== f"Permission set with id {permissionset_id} already has a typed link attachment to a manged policy with {managed_policy_arn}"
|
|
)
|
|
|
|
# test for managed policy that does not exist
|
|
not_exist_managed_policy_arn = "arn:aws:iam::aws:policy/DoesNotExist"
|
|
with pytest.raises(ClientError) as e:
|
|
client.attach_managed_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=not_exist_managed_policy_arn,
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ResourceNotFoundException"
|
|
assert (
|
|
err["Message"]
|
|
== "Policy does not exist with ARN: arn:aws:iam::aws:policy/DoesNotExist"
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_list_managed_policies_quota_limit(managed_policies):
|
|
"""
|
|
Tests exceeding the managed policy quota limit.
|
|
"""
|
|
managed_policies_to_attach = []
|
|
policy_count = 0
|
|
for policy_name in managed_policies:
|
|
path = managed_policies[policy_name]["Path"]
|
|
# only attach policies with path "/"
|
|
if path != "/":
|
|
continue
|
|
managed_policies_to_attach.append(policy_name)
|
|
policy_count += 1
|
|
if policy_count >= 21: # 20 is the quota limit
|
|
break
|
|
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
permission_set_arn = create_permissionset(client)
|
|
permission_set_id = permission_set_arn.split("/")[-1]
|
|
|
|
arn_string = "arn:aws:iam::aws:policy/"
|
|
with pytest.raises(ClientError) as e:
|
|
# the 21st policy should exceed the quota limit
|
|
for managed_policy in managed_policies_to_attach:
|
|
client.attach_managed_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=arn_string + managed_policy,
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ServiceQuotaExceededException"
|
|
assert (
|
|
err["Message"]
|
|
== f"You have exceeded AWS SSO limits. Cannot create ManagedPolicy more than 20 for id {permission_set_id}. Please refer to https://docs.aws.amazon.com/singlesignon/latest/userguide/limits.html"
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_list_managed_policies_in_permission_set(managed_policies):
|
|
"""
|
|
Tests functionality of listing aws managed policies attached to a permission set.
|
|
This also tests the pagination functionality.
|
|
"""
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
|
|
arn_string = "arn:aws:iam::aws:policy/"
|
|
|
|
# create a dummy permission set
|
|
permission_set_arn = create_permissionset(client)
|
|
|
|
managed_policies_names = list(managed_policies.keys())
|
|
|
|
# attach 3 good managed policies
|
|
for idx in range(3):
|
|
managed_policy_name = managed_policies_names[idx]
|
|
|
|
client.attach_managed_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=arn_string + managed_policy_name,
|
|
)
|
|
|
|
response = client.list_managed_policies_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
MaxResults=2,
|
|
)
|
|
|
|
managed_policies = []
|
|
|
|
assert len(response["AttachedManagedPolicies"]) == 2
|
|
managed_policies.extend(response["AttachedManagedPolicies"])
|
|
next_token = response["NextToken"]
|
|
|
|
response = client.list_managed_policies_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
MaxResults=2,
|
|
NextToken=next_token,
|
|
)
|
|
|
|
assert len(response["AttachedManagedPolicies"]) == 1
|
|
managed_policies.extend(response["AttachedManagedPolicies"])
|
|
|
|
# ensure the 3 unique managed policies were returned
|
|
actual_managed_policy_names = [
|
|
managed_policy["Name"] for managed_policy in managed_policies
|
|
]
|
|
expected_managed_policy_names = managed_policies_names[:3]
|
|
assert all(
|
|
name in actual_managed_policy_names for name in expected_managed_policy_names
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_detach_managed_policy_from_permission_set():
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
permission_set_arn = create_permissionset(client)
|
|
managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
|
|
|
|
# test for managed policy that is not attached
|
|
with pytest.raises(ClientError) as e:
|
|
client.detach_managed_policy_from_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=managed_policy_arn,
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ResourceNotFoundException"
|
|
assert (
|
|
err["Message"] == f"Could not find ManagedPolicy with arn {managed_policy_arn}"
|
|
)
|
|
|
|
# attach managed policy
|
|
client.attach_managed_policy_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=managed_policy_arn,
|
|
)
|
|
|
|
# detach managed policy
|
|
client.detach_managed_policy_from_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
ManagedPolicyArn=managed_policy_arn,
|
|
)
|
|
|
|
# ensure managed policy is detached
|
|
response = client.list_managed_policies_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert len(response["AttachedManagedPolicies"]) == 0
|
|
|
|
|
|
@mock_aws
|
|
def test_attach_customer_managed_policy_reference_to_permission_set():
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
permission_set_arn = create_permissionset(client)
|
|
|
|
policy_name = "test-policy"
|
|
policy_path = "/test-path/"
|
|
|
|
client.attach_customer_managed_policy_reference_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={
|
|
"Name": policy_name,
|
|
"Path": policy_path,
|
|
},
|
|
)
|
|
|
|
response = client.list_customer_managed_policy_references_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert len(response["CustomerManagedPolicyReferences"]) == 1
|
|
assert response["CustomerManagedPolicyReferences"][0]["Name"] == policy_name
|
|
assert response["CustomerManagedPolicyReferences"][0]["Path"] == policy_path
|
|
|
|
# test for customer managed policy that is already attached
|
|
with pytest.raises(ClientError) as e:
|
|
client.attach_customer_managed_policy_reference_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={
|
|
"Name": policy_name,
|
|
"Path": policy_path,
|
|
},
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ConflictException"
|
|
assert (
|
|
err["Message"]
|
|
== f"Given customer managed policy with name: {policy_name} and path {policy_path} already attached"
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_list_customer_managed_policy_references_in_permission_set():
|
|
"""
|
|
Tests listing customer managed policies including pagination.
|
|
"""
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
permission_set_arn = create_permissionset(client)
|
|
|
|
policy_name = "test-policy-"
|
|
|
|
# attach 3 customer managed policies
|
|
for idx in range(3):
|
|
client.attach_customer_managed_policy_reference_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={"Name": f"{policy_name}{idx}"},
|
|
)
|
|
|
|
response = client.list_customer_managed_policy_references_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
MaxResults=2,
|
|
)
|
|
|
|
customer_managed_policy_names = []
|
|
|
|
assert len(response["CustomerManagedPolicyReferences"]) == 2
|
|
next_token = response["NextToken"]
|
|
for name in response["CustomerManagedPolicyReferences"]:
|
|
customer_managed_policy_names.append(name["Name"])
|
|
|
|
response = client.list_customer_managed_policy_references_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
MaxResults=2,
|
|
NextToken=next_token,
|
|
)
|
|
for name in response["CustomerManagedPolicyReferences"]:
|
|
customer_managed_policy_names.append(name["Name"])
|
|
|
|
assert len(response["CustomerManagedPolicyReferences"]) == 1
|
|
|
|
# ensure the 3 unique customer managed policies were returned
|
|
assert len(set(customer_managed_policy_names)) == 3
|
|
|
|
|
|
@mock_aws
|
|
def test_detach_customer_managed_policy_reference_from_permission_set():
|
|
client = boto3.client("sso-admin", region_name="us-east-1")
|
|
permission_set_arn = create_permissionset(client)
|
|
|
|
# trying to detach a policy that doesn't exist yet
|
|
with pytest.raises(ClientError) as e:
|
|
client.detach_customer_managed_policy_reference_from_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={
|
|
"Name": "test-policy",
|
|
},
|
|
)
|
|
err = e.value.response["Error"]
|
|
assert err["Code"] == "ResourceNotFoundException"
|
|
assert (
|
|
err["Message"]
|
|
== "Given managed policy with name: test-policy and path / does not exist on PermissionSet"
|
|
)
|
|
|
|
# attach a policy
|
|
client.attach_customer_managed_policy_reference_to_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={
|
|
"Name": "test-policy",
|
|
"Path": "/some-path/",
|
|
},
|
|
)
|
|
|
|
# try to detach the policy but default path (should fail)
|
|
with pytest.raises(ClientError) as e:
|
|
client.detach_customer_managed_policy_reference_from_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={
|
|
"Name": "test-policy",
|
|
},
|
|
)
|
|
|
|
# detach the policy
|
|
client.detach_customer_managed_policy_reference_from_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
CustomerManagedPolicyReference={
|
|
"Name": "test-policy",
|
|
"Path": "/some-path/",
|
|
},
|
|
)
|
|
|
|
# ensure policy is detached
|
|
response = client.list_customer_managed_policy_references_in_permission_set(
|
|
InstanceArn=DUMMY_INSTANCE_ARN,
|
|
PermissionSetArn=permission_set_arn,
|
|
)
|
|
|
|
assert len(response["CustomerManagedPolicyReferences"]) == 0
|