moto/tests/test_ssoadmin/test_ssoadmin_policies.py

481 lines
16 KiB
Python
Raw Normal View History

import json
import boto3
import pytest
from botocore.exceptions import ClientError
2024-01-07 12:03:33 +00:00
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"]
2024-01-07 12:03:33 +00:00
@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"
2024-01-07 12:03:33 +00:00
@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"] == ""
2024-01-07 12:03:33 +00:00
@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"] == ""
2024-01-07 12:03:33 +00:00
@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"
)
2024-01-07 12:03:33 +00:00
@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"
)
2024-01-07 12:03:33 +00:00
@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
)
2024-01-07 12:03:33 +00:00
@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
2024-01-07 12:03:33 +00:00
@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"
)
2024-01-07 12:03:33 +00:00
@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
2024-01-07 12:03:33 +00:00
@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