moto/tests/test_ssoadmin/test_ssoadmin_policies.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

481 lines
16 KiB
Python
Raw Normal View History

import json
import boto3
import pytest
from botocore.exceptions import ClientError
from moto import mock_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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_ssoadmin
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