1498 lines
44 KiB
Python
1498 lines
44 KiB
Python
import boto3
|
|
import yaml
|
|
import sure # noqa
|
|
|
|
import pytest
|
|
from botocore.exceptions import ClientError
|
|
|
|
from moto import mock_iam, mock_cloudformation, mock_s3, mock_sts
|
|
from moto.core import ACCOUNT_ID
|
|
|
|
|
|
TEMPLATE_MINIMAL_ROLE = """
|
|
AWSTemplateFormatVersion: 2010-09-09
|
|
Resources:
|
|
RootRole:
|
|
Type: 'AWS::IAM::Role'
|
|
Properties:
|
|
AssumeRolePolicyDocument:
|
|
Version: 2012-10-17
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service:
|
|
- ec2.amazonaws.com
|
|
Action:
|
|
- 'sts:AssumeRole'
|
|
"""
|
|
|
|
|
|
TEMPLATE_ROLE_INSTANCE_PROFILE = """
|
|
AWSTemplateFormatVersion: 2010-09-09
|
|
Resources:
|
|
RootRole:
|
|
Type: 'AWS::IAM::Role'
|
|
Properties:
|
|
RoleName: {0}
|
|
AssumeRolePolicyDocument:
|
|
Version: 2012-10-17
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service:
|
|
- ec2.amazonaws.com
|
|
Action:
|
|
- 'sts:AssumeRole'
|
|
Path: /
|
|
Policies:
|
|
- PolicyName: root
|
|
PolicyDocument:
|
|
Version: 2012-10-17
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: '*'
|
|
Resource: '*'
|
|
RootInstanceProfile:
|
|
Type: 'AWS::IAM::InstanceProfile'
|
|
Properties:
|
|
Path: /
|
|
Roles:
|
|
- !Ref RootRole
|
|
"""
|
|
|
|
# AWS::IAM::User Tests
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_user():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
user_name = "MyUser"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
Properties:
|
|
UserName: {0}
|
|
""".strip().format(
|
|
user_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
provisioned_resource["LogicalResourceId"].should.equal("TheUser")
|
|
provisioned_resource["PhysicalResourceId"].should.equal(user_name)
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_user_no_interruption():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
user_name = provisioned_resource["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)["User"]
|
|
user["Path"].should.equal("/")
|
|
|
|
path = "/MyPath/"
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
Properties:
|
|
Path: {0}
|
|
""".strip().format(
|
|
path
|
|
)
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
user = iam_client.get_user(UserName=user_name)["User"]
|
|
user["Path"].should.equal(path)
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_user_replacement():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
original_user_name = provisioned_resource["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=original_user_name)["User"]
|
|
user["Path"].should.equal("/")
|
|
|
|
new_user_name = "MyUser"
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
Properties:
|
|
UserName: {0}
|
|
""".strip().format(
|
|
new_user_name
|
|
)
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
with pytest.raises(ClientError) as e:
|
|
iam_client.get_user(UserName=original_user_name)
|
|
e.value.response["Error"]["Code"].should.equal("NoSuchEntity")
|
|
|
|
iam_client.get_user(UserName=new_user_name)
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_drop_user():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheFirstUser:
|
|
Type: AWS::IAM::User
|
|
TheSecondUser:
|
|
Type: AWS::IAM::User
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
first_provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheFirstUser"
|
|
][0]
|
|
second_provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheSecondUser"
|
|
][0]
|
|
first_user_name = first_provisioned_user["PhysicalResourceId"]
|
|
second_user_name = second_provisioned_user["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
iam_client.get_user(UserName=first_user_name)
|
|
iam_client.get_user(UserName=second_user_name)
|
|
|
|
template = """
|
|
Resources:
|
|
TheSecondUser:
|
|
Type: AWS::IAM::User
|
|
""".strip()
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
len(provisioned_resources).should.equal(1)
|
|
second_provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheSecondUser"
|
|
][0]
|
|
second_user_name.should.equal(second_provisioned_user["PhysicalResourceId"])
|
|
|
|
iam_client.get_user(UserName=second_user_name)
|
|
with pytest.raises(ClientError) as e:
|
|
iam_client.get_user(UserName=first_user_name)
|
|
e.value.response["Error"]["Code"].should.equal("NoSuchEntity")
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_delete_user():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
user_name = "MyUser"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
Properties:
|
|
UserName: {}
|
|
""".strip().format(
|
|
user_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
|
|
with pytest.raises(ClientError) as e:
|
|
user = iam_client.get_user(UserName=user_name)
|
|
e.value.response["Error"]["Code"].should.equal("NoSuchEntity")
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_delete_user_having_generated_name():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
provisioned_resource["LogicalResourceId"].should.equal("TheUser")
|
|
user_name = provisioned_resource["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
|
|
with pytest.raises(ClientError) as e:
|
|
user = iam_client.get_user(UserName=user_name)
|
|
e.value.response["Error"]["Code"].should.equal("NoSuchEntity")
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_user_get_attr():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
user_name = "MyUser"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
Properties:
|
|
UserName: {0}
|
|
Outputs:
|
|
UserName:
|
|
Value: !Ref TheUser
|
|
UserArn:
|
|
Value: !GetAtt TheUser.Arn
|
|
""".strip().format(
|
|
user_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
stack_description = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
|
output_user_name = [
|
|
output["OutputValue"]
|
|
for output in stack_description["Outputs"]
|
|
if output["OutputKey"] == "UserName"
|
|
][0]
|
|
output_user_arn = [
|
|
output["OutputValue"]
|
|
for output in stack_description["Outputs"]
|
|
if output["OutputKey"] == "UserArn"
|
|
][0]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user_description = iam_client.get_user(UserName=output_user_name)["User"]
|
|
output_user_arn.should.equal(user_description["Arn"])
|
|
|
|
|
|
# AWS::IAM::ManagedPolicy Tests
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_managed_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::ManagedPolicy
|
|
Properties:
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: '*'
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
policy_arn = provisioned_resource["PhysicalResourceId"]
|
|
policy_arn.should.match(
|
|
"arn:aws:iam::{}:policy/MyStack-ThePolicy-[A-Z0-9]+".format(ACCOUNT_ID)
|
|
)
|
|
expected_name = policy_arn.split("/")[1]
|
|
|
|
response = iam_client.list_entities_for_policy(PolicyArn=policy_arn)
|
|
response.should.have.key("PolicyGroups").equal([])
|
|
response.should.have.key("PolicyUsers").equal([])
|
|
response.should.have.key("PolicyRoles").equal([])
|
|
|
|
policy = iam_client.get_policy(PolicyArn=policy_arn)["Policy"]
|
|
policy.should.have.key("Arn").equal(policy_arn)
|
|
policy.should.have.key("PolicyName").equal(expected_name)
|
|
policy.should.have.key("Description").equal("")
|
|
policy.should.have.key("Path").equal("/")
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_managed_policy_with_additional_properties():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
name = "FancyManagedPolicy"
|
|
desc = "Custom managed policy with name"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::ManagedPolicy
|
|
Properties:
|
|
Description: {0}
|
|
Path: /
|
|
ManagedPolicyName: {1}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: '*'
|
|
""".strip().format(
|
|
desc, name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
policy_arn = provisioned_resource["PhysicalResourceId"]
|
|
policy_arn.should.equal("arn:aws:iam::{}:policy/{}".format(ACCOUNT_ID, name))
|
|
|
|
policy = iam_client.get_policy(PolicyArn=policy_arn)["Policy"]
|
|
policy.should.have.key("Arn").equal(policy_arn)
|
|
policy.should.have.key("Path").equal("/")
|
|
policy.should.have.key("Description").equal(desc)
|
|
policy.should.have.key("PolicyName").equal(name)
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_managed_policy_attached_to_a_group():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
group_name = "MyGroup"
|
|
iam_client.create_group(GroupName=group_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
desc = "Custom managed policy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::ManagedPolicy
|
|
Properties:
|
|
Description: {0}
|
|
Path: /
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: '*'
|
|
Groups:
|
|
- {1}
|
|
""".strip().format(
|
|
desc, group_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
policy_arn = provisioned_resource["PhysicalResourceId"]
|
|
policy_arn.should.match(
|
|
"rn:aws:iam::{}:policy/MyStack-ThePolicy-[A-Z0-9]+".format(ACCOUNT_ID)
|
|
)
|
|
|
|
response = iam_client.list_entities_for_policy(PolicyArn=policy_arn)
|
|
response.should.have.key("PolicyGroups").equal([{"GroupName": group_name}])
|
|
response.should.have.key("PolicyUsers").equal([])
|
|
response.should.have.key("PolicyRoles").equal([])
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_managed_policy_attached_to_a_user():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user_name = "MyUser"
|
|
iam_client.create_user(UserName=user_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
desc = "Custom managed policy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::ManagedPolicy
|
|
Properties:
|
|
Description: {0}
|
|
Path: /
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: '*'
|
|
Users:
|
|
- {1}
|
|
""".strip().format(
|
|
desc, user_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
policy_arn = provisioned_resource["PhysicalResourceId"]
|
|
policy_arn.should.match(
|
|
"rn:aws:iam::{}:policy/MyStack-ThePolicy-[A-Z0-9]+".format(ACCOUNT_ID)
|
|
)
|
|
|
|
response = iam_client.list_entities_for_policy(PolicyArn=policy_arn)
|
|
response.should.have.key("PolicyGroups").equal([])
|
|
response.should.have.key("PolicyUsers").equal([{"UserName": user_name}])
|
|
response.should.have.key("PolicyRoles").equal([])
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_managed_policy_attached_to_a_role():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
role_name = "MyRole"
|
|
iam_client.create_role(RoleName=role_name, AssumeRolePolicyDocument="some policy")
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
desc = "Custom managed policy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::ManagedPolicy
|
|
Properties:
|
|
Description: {0}
|
|
Path: /
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: '*'
|
|
Roles:
|
|
- {1}
|
|
""".strip().format(
|
|
desc, role_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
policy_arn = provisioned_resource["PhysicalResourceId"]
|
|
policy_arn.should.match(
|
|
"rn:aws:iam::{}:policy/MyStack-ThePolicy-[A-Z0-9]+".format(ACCOUNT_ID)
|
|
)
|
|
|
|
response = iam_client.list_entities_for_policy(PolicyArn=policy_arn)
|
|
response.should.have.key("PolicyGroups").equal([])
|
|
response.should.have.key("PolicyUsers").equal([])
|
|
response.should.have.key("PolicyRoles").equal([{"RoleName": role_name}])
|
|
|
|
|
|
# AWS::IAM::Policy Tests
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_user_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user_name = "MyUser"
|
|
iam_client.create_user(UserName=user_name)
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
bucket = s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {1}
|
|
Users:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, user_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_user_policy(UserName=user_name, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_user_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user_name_1 = "MyUser1"
|
|
iam_client.create_user(UserName=user_name_1)
|
|
user_name_2 = "MyUser2"
|
|
iam_client.create_user(UserName=user_name_2)
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {1}
|
|
Users:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, user_name_1
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_user_policy(UserName=user_name_1, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
# Change template and user
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:ListBuckets
|
|
Resource: {1}
|
|
Users:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, user_name_2
|
|
)
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_user_policy(UserName=user_name_2, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
iam_client.get_user_policy.when.called_with(
|
|
UserName=user_name_1, PolicyName=policy_name
|
|
).should.throw(iam_client.exceptions.NoSuchEntityException)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_delete_user_policy_having_generated_name():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user_name = "MyUser"
|
|
iam_client.create_user(UserName=user_name)
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
bucket = s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: MyPolicy
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {0}
|
|
Users:
|
|
- {1}
|
|
""".strip().format(
|
|
bucket_arn, user_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_user_policy(UserName=user_name, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
iam_client.get_user_policy.when.called_with(
|
|
UserName=user_name, PolicyName=policy_name
|
|
).should.throw(iam_client.exceptions.NoSuchEntityException)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_role_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
role_name = "MyRole"
|
|
iam_client.create_role(RoleName=role_name, AssumeRolePolicyDocument="{}")
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {1}
|
|
Roles:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, role_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_role_policy(RoleName=role_name, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_role_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
role_name_1 = "MyRole1"
|
|
iam_client.create_role(RoleName=role_name_1, AssumeRolePolicyDocument="{}")
|
|
role_name_2 = "MyRole2"
|
|
iam_client.create_role(RoleName=role_name_2, AssumeRolePolicyDocument="{}")
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {1}
|
|
Roles:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, role_name_1
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_role_policy(RoleName=role_name_1, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
# Change template and user
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:ListBuckets
|
|
Resource: {1}
|
|
Roles:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, role_name_2
|
|
)
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_role_policy(RoleName=role_name_2, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
iam_client.get_role_policy.when.called_with(
|
|
RoleName=role_name_1, PolicyName=policy_name
|
|
).should.throw(iam_client.exceptions.NoSuchEntityException)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_delete_role_policy_having_generated_name():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
role_name = "MyRole"
|
|
iam_client.create_role(RoleName=role_name, AssumeRolePolicyDocument="{}")
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: MyPolicy
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {0}
|
|
Roles:
|
|
- {1}
|
|
""".strip().format(
|
|
bucket_arn, role_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_role_policy(RoleName=role_name, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
iam_client.get_role_policy.when.called_with(
|
|
RoleName=role_name, PolicyName=policy_name
|
|
).should.throw(iam_client.exceptions.NoSuchEntityException)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_group_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
group_name = "MyGroup"
|
|
iam_client.create_group(GroupName=group_name)
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {1}
|
|
Groups:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, group_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_group_policy(GroupName=group_name, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_group_policy():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
group_name_1 = "MyGroup1"
|
|
iam_client.create_group(GroupName=group_name_1)
|
|
group_name_2 = "MyGroup2"
|
|
iam_client.create_group(GroupName=group_name_2)
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {1}
|
|
Groups:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, group_name_1
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_group_policy(GroupName=group_name_1, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
# Change template and user
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: {0}
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:ListBuckets
|
|
Resource: {1}
|
|
Groups:
|
|
- {2}
|
|
""".strip().format(
|
|
policy_name, bucket_arn, group_name_2
|
|
)
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_group_policy(GroupName=group_name_2, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
iam_client.get_group_policy.when.called_with(
|
|
GroupName=group_name_1, PolicyName=policy_name
|
|
).should.throw(iam_client.exceptions.NoSuchEntityException)
|
|
|
|
|
|
@mock_s3
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_delete_group_policy_having_generated_name():
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
group_name = "MyGroup"
|
|
iam_client.create_group(GroupName=group_name)
|
|
|
|
s3_client = boto3.client("s3", region_name="us-east-1")
|
|
bucket_name = "my-bucket"
|
|
s3_client.create_bucket(Bucket=bucket_name)
|
|
bucket_arn = "arn:aws:s3:::{0}".format(bucket_name)
|
|
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
stack_name = "MyStack"
|
|
policy_name = "MyPolicy"
|
|
|
|
template = """
|
|
Resources:
|
|
ThePolicy:
|
|
Type: AWS::IAM::Policy
|
|
Properties:
|
|
PolicyName: MyPolicy
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:*
|
|
Resource: {0}
|
|
Groups:
|
|
- {1}
|
|
""".strip().format(
|
|
bucket_arn, group_name
|
|
)
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resource = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
][0]
|
|
logical_resource_id = provisioned_resource["LogicalResourceId"]
|
|
logical_resource_id.should.equal("ThePolicy")
|
|
|
|
original_policy_document = yaml.load(template, Loader=yaml.FullLoader)["Resources"][
|
|
logical_resource_id
|
|
]["Properties"]["PolicyDocument"]
|
|
policy = iam_client.get_group_policy(GroupName=group_name, PolicyName=policy_name)
|
|
policy["PolicyDocument"].should.equal(original_policy_document)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
iam_client.get_group_policy.when.called_with(
|
|
GroupName=group_name, PolicyName=policy_name
|
|
).should.throw(iam_client.exceptions.NoSuchEntityException)
|
|
|
|
|
|
# AWS::IAM::User AccessKeys
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_user_with_access_key():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
UserName: !Ref TheUser
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
|
|
provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheUser"
|
|
][0]
|
|
user_name = provisioned_user["PhysicalResourceId"]
|
|
|
|
provisioned_access_keys = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheAccessKey"
|
|
]
|
|
len(provisioned_access_keys).should.equal(1)
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)["User"]
|
|
user["UserName"].should.equal(user_name)
|
|
access_keys = iam_client.list_access_keys(UserName=user_name)
|
|
access_keys["AccessKeyMetadata"][0]["UserName"].should.equal(user_name)
|
|
|
|
|
|
@mock_sts
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_access_key_get_attr():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
UserName: !Ref TheUser
|
|
Outputs:
|
|
AccessKeyId:
|
|
Value: !Ref TheAccessKey
|
|
SecretKey:
|
|
Value: !GetAtt TheAccessKey.SecretAccessKey
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheUser"
|
|
][0]
|
|
user_name = provisioned_user["PhysicalResourceId"]
|
|
|
|
stack_description = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
|
|
output_access_key_id = [
|
|
output["OutputValue"]
|
|
for output in stack_description["Outputs"]
|
|
if output["OutputKey"] == "AccessKeyId"
|
|
][0]
|
|
output_secret_key = [
|
|
output["OutputValue"]
|
|
for output in stack_description["Outputs"]
|
|
if output["OutputKey"] == "SecretKey"
|
|
][0]
|
|
|
|
sts_client = boto3.client(
|
|
"sts",
|
|
aws_access_key_id=output_access_key_id,
|
|
aws_secret_access_key=output_secret_key,
|
|
region_name="us-east-1",
|
|
)
|
|
caller_identity = sts_client.get_caller_identity()
|
|
caller_identity["Arn"].split("/")[1].should.equal(user_name)
|
|
pass
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_delete_users_access_key():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
UserName: !Ref TheUser
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
|
|
provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheUser"
|
|
][0]
|
|
user_name = provisioned_user["PhysicalResourceId"]
|
|
|
|
provisioned_access_keys = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheAccessKey"
|
|
]
|
|
provisioned_access_keys.should.have.length_of(1)
|
|
access_key_id = provisioned_access_keys[0]["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)["User"]
|
|
user["UserName"].should.equal(user_name)
|
|
access_keys = iam_client.list_access_keys(UserName=user_name)
|
|
access_keys["AccessKeyMetadata"][0]["AccessKeyId"].should.equal(access_key_id)
|
|
access_keys["AccessKeyMetadata"][0]["UserName"].should.equal(user_name)
|
|
access_key_id.should.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"])
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
|
|
iam_client.get_user.when.called_with(UserName=user_name).should.throw(
|
|
iam_client.exceptions.NoSuchEntityException
|
|
)
|
|
iam_client.list_access_keys.when.called_with(UserName=user_name).should.throw(
|
|
iam_client.exceptions.NoSuchEntityException
|
|
)
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_users_access_key_no_interruption():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
UserName: !Ref TheUser
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
|
|
provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheUser"
|
|
][0]
|
|
user_name = provisioned_user["PhysicalResourceId"]
|
|
|
|
provisioned_access_key = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheAccessKey"
|
|
][0]
|
|
access_key_id = provisioned_access_key["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)
|
|
access_keys = iam_client.list_access_keys(UserName=user_name)
|
|
access_key_id.should.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"])
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
Status: Inactive
|
|
""".strip()
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
access_keys = iam_client.list_access_keys(UserName=user_name)
|
|
access_keys["AccessKeyMetadata"][0]["Status"].should.equal("Inactive")
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_update_users_access_key_replacement():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
UserName: !Ref TheUser
|
|
""".strip()
|
|
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
provisioned_resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
|
|
provisioned_user = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheUser"
|
|
][0]
|
|
user_name = provisioned_user["PhysicalResourceId"]
|
|
|
|
provisioned_access_key = [
|
|
resource
|
|
for resource in provisioned_resources
|
|
if resource["LogicalResourceId"] == "TheAccessKey"
|
|
][0]
|
|
access_key_id = provisioned_access_key["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
user = iam_client.get_user(UserName=user_name)
|
|
access_keys = iam_client.list_access_keys(UserName=user_name)
|
|
access_key_id.should.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"])
|
|
|
|
other_user_name = "MyUser"
|
|
iam_client.create_user(UserName=other_user_name)
|
|
|
|
template = """
|
|
Resources:
|
|
TheUser:
|
|
Type: AWS::IAM::User
|
|
TheAccessKey:
|
|
Type: AWS::IAM::AccessKey
|
|
Properties:
|
|
UserName: {0}
|
|
""".strip().format(
|
|
other_user_name
|
|
)
|
|
|
|
cf_client.update_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
access_keys = iam_client.list_access_keys(UserName=user_name)
|
|
len(access_keys["AccessKeyMetadata"]).should.equal(0)
|
|
|
|
access_keys = iam_client.list_access_keys(UserName=other_user_name)
|
|
access_key_id.should_not.equal(access_keys["AccessKeyMetadata"][0]["AccessKeyId"])
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_role():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
|
|
template = TEMPLATE_MINIMAL_ROLE.strip()
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
role = [res for res in resources if res["ResourceType"] == "AWS::IAM::Role"][0]
|
|
role["LogicalResourceId"].should.equal("RootRole")
|
|
role_name = role["PhysicalResourceId"]
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
iam_client.list_roles()["Roles"].should.have.length_of(1)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
|
|
iam_client.list_roles()["Roles"].should.have.length_of(0)
|
|
|
|
|
|
@mock_iam
|
|
@mock_cloudformation
|
|
def test_iam_cloudformation_create_role_and_instance_profile():
|
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
|
|
|
stack_name = "MyStack"
|
|
role_name = "MyUser"
|
|
|
|
template = TEMPLATE_ROLE_INSTANCE_PROFILE.strip().format(role_name)
|
|
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
|
|
|
|
resources = cf_client.list_stack_resources(StackName=stack_name)[
|
|
"StackResourceSummaries"
|
|
]
|
|
role = [res for res in resources if res["ResourceType"] == "AWS::IAM::Role"][0]
|
|
role["LogicalResourceId"].should.equal("RootRole")
|
|
role["PhysicalResourceId"].should.equal(role_name)
|
|
profile = [
|
|
res for res in resources if res["ResourceType"] == "AWS::IAM::InstanceProfile"
|
|
][0]
|
|
profile["LogicalResourceId"].should.equal("RootInstanceProfile")
|
|
profile["PhysicalResourceId"].should.contain(
|
|
stack_name
|
|
) # e.g. MyStack-RootInstanceProfile-73Y4H4ALFW3N
|
|
profile["PhysicalResourceId"].should.contain("RootInstanceProfile")
|
|
|
|
iam_client = boto3.client("iam", region_name="us-east-1")
|
|
iam_client.list_roles()["Roles"].should.have.length_of(1)
|
|
|
|
cf_client.delete_stack(StackName=stack_name)
|
|
|
|
iam_client.list_roles()["Roles"].should.have.length_of(0)
|