333 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			333 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from datetime import datetime
 | |
| 
 | |
| import boto3
 | |
| import sure  # noqa  # pylint: disable=unused-import
 | |
| import json
 | |
| 
 | |
| import pytest
 | |
| from botocore.exceptions import ClientError
 | |
| from moto import mock_iam
 | |
| from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
 | |
| 
 | |
| MOCK_POLICY = """
 | |
| {
 | |
|   "Version": "2012-10-17",
 | |
|   "Statement":
 | |
|     {
 | |
|       "Effect": "Allow",
 | |
|       "Action": "s3:ListBucket",
 | |
|       "Resource": "arn:aws:s3:::example_bucket"
 | |
|     }
 | |
| }
 | |
| """
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_create_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.create_group(GroupName="my-group")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("Group my-group already exists")
 | |
|     err["Message"].should.equal(None)
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_get_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     created = conn.create_group(GroupName="my-group")["Group"]
 | |
|     created["Path"].should.equal("/")
 | |
|     created["GroupName"].should.equal("my-group")
 | |
|     created.should.have.key("GroupId")
 | |
|     created["Arn"].should.equal(f"arn:aws:iam::{ACCOUNT_ID}:group/my-group")
 | |
|     created["CreateDate"].should.be.a(datetime)
 | |
| 
 | |
|     retrieved = conn.get_group(GroupName="my-group")["Group"]
 | |
|     retrieved.should.equal(created)
 | |
| 
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.get_group(GroupName="not-group")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("Group not-group not found")
 | |
| 
 | |
| 
 | |
| @mock_iam()
 | |
| def test_get_group_current():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     result = conn.get_group(GroupName="my-group")
 | |
| 
 | |
|     assert result["Group"]["Path"] == "/"
 | |
|     assert result["Group"]["GroupName"] == "my-group"
 | |
|     assert isinstance(result["Group"]["CreateDate"], datetime)
 | |
|     assert result["Group"]["GroupId"]
 | |
|     assert result["Group"]["Arn"] == f"arn:aws:iam::{ACCOUNT_ID}:group/my-group"
 | |
|     assert not result["Users"]
 | |
| 
 | |
|     # Make a group with a different path:
 | |
|     other_group = conn.create_group(GroupName="my-other-group", Path="/some/location/")
 | |
|     assert other_group["Group"]["Path"] == "/some/location/"
 | |
|     assert (
 | |
|         other_group["Group"]["Arn"]
 | |
|         == f"arn:aws:iam::{ACCOUNT_ID}:group/some/location/my-other-group"
 | |
|     )
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_get_all_groups():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group1")
 | |
|     conn.create_group(GroupName="my-group2")
 | |
|     groups = conn.list_groups()["Groups"]
 | |
|     groups.should.have.length_of(2)
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_add_unknown_user_to_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.add_user_to_group(GroupName="my-group", UserName="my-user")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("The user with name my-user cannot be found.")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_add_user_to_unknown_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_user(UserName="my-user")
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.add_user_to_group(GroupName="my-group", UserName="my-user")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("Group my-group not found")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_add_user_to_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.create_user(UserName="my-user")
 | |
|     conn.add_user_to_group(GroupName="my-group", UserName="my-user")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_remove_user_from_unknown_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.remove_user_from_group(GroupName="my-group", UserName="my-user")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("Group my-group not found")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_remove_nonattached_user_from_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.create_user(UserName="my-user")
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.remove_user_from_group(GroupName="my-group", UserName="my-user")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("User my-user not in group my-group")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_remove_user_from_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.create_user(UserName="my-user")
 | |
|     conn.add_user_to_group(GroupName="my-group", UserName="my-user")
 | |
|     conn.remove_user_from_group(GroupName="my-group", UserName="my-user")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_add_user_should_be_idempotent():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.create_user(UserName="my-user")
 | |
|     # We'll add the same user twice, but it should only be persisted once
 | |
|     conn.add_user_to_group(GroupName="my-group", UserName="my-user")
 | |
|     conn.add_user_to_group(GroupName="my-group", UserName="my-user")
 | |
| 
 | |
|     conn.list_groups_for_user(UserName="my-user")["Groups"].should.have.length_of(1)
 | |
| 
 | |
|     # Which means that if we remove one, none should be left
 | |
|     conn.remove_user_from_group(GroupName="my-group", UserName="my-user")
 | |
| 
 | |
|     conn.list_groups_for_user(UserName="my-user")["Groups"].should.have.length_of(0)
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_get_groups_for_user():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group1")
 | |
|     conn.create_group(GroupName="my-group2")
 | |
|     conn.create_group(GroupName="other-group")
 | |
|     conn.create_user(UserName="my-user")
 | |
|     conn.add_user_to_group(GroupName="my-group1", UserName="my-user")
 | |
|     conn.add_user_to_group(GroupName="my-group2", UserName="my-user")
 | |
| 
 | |
|     groups = conn.list_groups_for_user(UserName="my-user")["Groups"]
 | |
|     groups.should.have.length_of(2)
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_put_group_policy():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.put_group_policy(
 | |
|         GroupName="my-group", PolicyName="my-policy", PolicyDocument=MOCK_POLICY
 | |
|     )
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_attach_group_policies():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.list_attached_group_policies(GroupName="my-group")[
 | |
|         "AttachedPolicies"
 | |
|     ].should.be.empty
 | |
|     policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role"
 | |
|     conn.list_attached_group_policies(GroupName="my-group")[
 | |
|         "AttachedPolicies"
 | |
|     ].should.be.empty
 | |
|     conn.attach_group_policy(GroupName="my-group", PolicyArn=policy_arn)
 | |
|     conn.list_attached_group_policies(GroupName="my-group")[
 | |
|         "AttachedPolicies"
 | |
|     ].should.equal(
 | |
|         [{"PolicyName": "AmazonElasticMapReduceforEC2Role", "PolicyArn": policy_arn}]
 | |
|     )
 | |
| 
 | |
|     conn.detach_group_policy(GroupName="my-group", PolicyArn=policy_arn)
 | |
|     conn.list_attached_group_policies(GroupName="my-group")[
 | |
|         "AttachedPolicies"
 | |
|     ].should.be.empty
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_get_group_policy():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     with pytest.raises(ClientError) as ex:
 | |
|         conn.get_group_policy(GroupName="my-group", PolicyName="my-policy")
 | |
|     err = ex.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("Policy my-policy not found")
 | |
| 
 | |
|     conn.put_group_policy(
 | |
|         GroupName="my-group", PolicyName="my-policy", PolicyDocument=MOCK_POLICY
 | |
|     )
 | |
|     policy = conn.get_group_policy(GroupName="my-group", PolicyName="my-policy")
 | |
|     policy["GroupName"].should.equal("my-group")
 | |
|     policy["PolicyName"].should.equal("my-policy")
 | |
|     policy["PolicyDocument"].should.equal(json.loads(MOCK_POLICY))
 | |
| 
 | |
| 
 | |
| @mock_iam()
 | |
| def test_list_group_policies():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     conn.list_group_policies(GroupName="my-group")["PolicyNames"].should.be.empty
 | |
|     conn.put_group_policy(
 | |
|         GroupName="my-group", PolicyName="my-policy", PolicyDocument=MOCK_POLICY
 | |
|     )
 | |
|     conn.list_group_policies(GroupName="my-group")["PolicyNames"].should.equal(
 | |
|         ["my-policy"]
 | |
|     )
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_delete_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     groups = conn.list_groups()
 | |
|     assert groups["Groups"][0]["GroupName"] == "my-group"
 | |
|     assert len(groups["Groups"]) == 1
 | |
|     conn.delete_group(GroupName="my-group")
 | |
|     conn.list_groups()["Groups"].should.be.empty
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_delete_unknown_group():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     with pytest.raises(ClientError) as err:
 | |
|         conn.delete_group(GroupName="unknown-group")
 | |
|     err.value.response["Error"]["Code"].should.equal("NoSuchEntity")
 | |
|     err.value.response["Error"]["Message"].should.equal(
 | |
|         "The group with name unknown-group cannot be found."
 | |
|     )
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_update_group_name():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group")
 | |
|     initial_group = conn.get_group(GroupName="my-group")["Group"]
 | |
| 
 | |
|     conn.update_group(GroupName="my-group", NewGroupName="new-group")
 | |
| 
 | |
|     # The old group-name should no longer exist
 | |
|     with pytest.raises(ClientError) as exc:
 | |
|         conn.get_group(GroupName="my-group")
 | |
|     exc.value.response["Error"]["Code"].should.equal("NoSuchEntity")
 | |
| 
 | |
|     result = conn.get_group(GroupName="new-group")["Group"]
 | |
|     result["Path"].should.equal("/")
 | |
|     result["GroupName"].should.equal("new-group")
 | |
|     result["GroupId"].should.equal(initial_group["GroupId"])
 | |
|     result["Arn"].should.match(":group/new-group")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_update_group_name_that_has_a_path():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group", Path="/path")
 | |
| 
 | |
|     conn.update_group(GroupName="my-group", NewGroupName="new-group")
 | |
| 
 | |
|     # Verify the path hasn't changed
 | |
|     new = conn.get_group(GroupName="new-group")["Group"]
 | |
|     new["Path"].should.equal("/path")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_update_group_path():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="my-group", Path="/path")
 | |
| 
 | |
|     conn.update_group(
 | |
|         GroupName="my-group", NewGroupName="new-group", NewPath="/new-path"
 | |
|     )
 | |
| 
 | |
|     # Verify the path has changed
 | |
|     new = conn.get_group(GroupName="new-group")["Group"]
 | |
|     new["Path"].should.equal("/new-path")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_update_group_that_does_not_exist():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
| 
 | |
|     with pytest.raises(ClientError) as exc:
 | |
|         conn.update_group(GroupName="nonexisting", NewGroupName="..")
 | |
|     err = exc.value.response["Error"]
 | |
|     err["Code"].should.equal("NoSuchEntity")
 | |
|     err["Message"].should.equal("The group with name nonexisting cannot be found.")
 | |
| 
 | |
| 
 | |
| @mock_iam
 | |
| def test_update_group_with_existing_name():
 | |
|     conn = boto3.client("iam", region_name="us-east-1")
 | |
|     conn.create_group(GroupName="existing1")
 | |
|     conn.create_group(GroupName="existing2")
 | |
| 
 | |
|     with pytest.raises(ClientError) as exc:
 | |
|         conn.update_group(GroupName="existing1", NewGroupName="existing2")
 | |
|     err = exc.value.response["Error"]
 | |
|     err["Code"].should.equal("Conflict")
 | |
|     err["Message"].should.equal("Group existing2 already exists")
 |