Here step by a step python code to create IAM role.
This is not production ready code. It is just as a sample.
CreateRole.py
from awacs.aws import Allow, Deny, Statement, Principal, Policy, Action
from troposphere import Template, Ref, GetAtt, Output
from troposphere.iam import Role, PolicyType
from awacs.sts import AssumeRole
from libs.common import *
class CfTemplate(object):
template = Template()
@classmethod
def resource_title(cls, name):
camel_case_name = name.title().replace("_", "").replace("-", "")
return camel_case_name
class Security(CfTemplate):
@classmethod
def create_admin_role(cls, name):
admin_role = CfTemplate.template.add_resource(Role(
"%sRole" % CfTemplate.resource_title(name),
AssumeRolePolicyDocument=Policy(
Statement=[
Statement(Effect=Allow,
Principal=Principal("Service", ["ec2.amazonaws.com"]),
Action=[AssumeRole], )
]
),
ManagedPolicyArns=[
"arn:aws:iam::aws:policy/AdministratorAccess"
]
))
CfTemplate.template.add_output(
Output(
"%sOutput" % cls.resource_title(name),
Description="RoleArn",
Value=GetAtt(admin_role, "Arn")
)
)
return admin_role
@classmethod
def create_developer_role(cls, name):
dev_role = CfTemplate.template.add_resource(Role(
"%sRole" % CfTemplate.resource_title(name),
AssumeRolePolicyDocument=Policy(
Statement=[
Statement(Effect=Allow,
Principal=Principal("Service", ["ec2.amazonaws.com"]),
Action=[AssumeRole], )
]
),
ManagedPolicyArns=[
"arn:aws:iam::aws:policy/AWSElasticBeanstalkFullAccess",
"arn:aws:iam::aws:policy/AmazonElasticMapReduceFullAccess",
"arn:aws:iam::aws:policy/service-role/AWSDataPipelineRole"
]
))
CfTemplate.template.add_output(
Output(
"%sOutput" % cls.resource_title(name),
Description="RoleArn",
Value=GetAtt(dev_role, "Arn")
)
)
return dev_role
@classmethod
def create_developer_policy(cls, developer_role):
developer_policy = CfTemplate.template.add_resource(PolicyType(
"DeveloperPolicy",
PolicyName="DeveloperPolicy",
Roles=[Ref(developer_role)],
PolicyDocument=Policy(
Statement=[
Statement(
Effect=Deny,
Action=[
# VPCs
Action("ec2", "CreateVpc"),
Action("ec2", "ModifyVpcAttribute"),
Action("ec2", "DeleteVpc"),
# VPC endpoints
Action("ec2", "CreateVpcEndpoint"),
Action("ec2", "ModifyVpcEndpoint"),
Action("ec2", "DeleteVpcEndpoints"),
# VPC classic
Action("ec2", "AttachClassicLinkVpc"),
Action("ec2", "DetachClassicLinkVpc"),
Action("ec2", "EnableVpcClassicLink"),
Action("ec2", "DisableVpcClassicLink"),
Action("ec2", "EnableVpcClassicLinkDnsSupport"),
Action("ec2", "DisableVpcClassicLinkDnsSupport"),
# VPC peerings
Action("ec2", "CreateVpcPeeringConnection"),
Action("ec2", "ModifyVpcPeeringConnectionOptions"),
Action("ec2", "RejectVpcPeeringConnection"),
Action("ec2", "DeleteVpcPeeringConnection"),
# Subnets
Action("ec2", "CreateSubnet"),
Action("ec2", "DeleteSubnet"),
Action("ec2", "ModifySubnetAttribute"),
# Route Tables
Action("ec2", "AssociateRouteTable"),
Action("ec2", "ReplaceRouteTableAssociation"),
Action("ec2", "DisassociateRouteTable"),
# Routes
Action("ec2", "CreateRoute"),
Action("ec2", "ReplaceRoute"),
Action("ec2", "DeleteRoute"),
Action("ec2", "CreateRouteTable"),
Action("ec2", "DeleteRouteTable"),
# VPN routing
Action("ec2", "CreateVpnConnectionRoute"),
Action("ec2", "DeleteVpnConnectionRoute"),
Action("ec2", "EnableVgwRoutePropagation"),
Action("ec2", "DisableVgwRoutePropagation"),
# Customer Gateways
Action("ec2", "CreateCustomerGateway"),
Action("ec2", "DeleteCustomerGateway"),
# VPN Gateways
Action("ec2", "CreateVpnGateway"),
Action("ec2", "DeleteVpnGateway"),
Action("ec2", "CreateVpnConnection"),
Action("ec2", "DeleteVpnConnection"),
Action("ec2", "CreateVpnConnectionRoute"),
Action("ec2", "DeleteVpnConnectionRoute"),
Action("ec2", "AttachVpnGateway"),
Action("ec2", "DetachVpnGateway"),
# Network ACLs
Action("ec2", "CreateNetworkAcl"),
Action("ec2", "DeleteNetworkAcl"),
Action("ec2", "CreateNetworkAclEntry"),
Action("ec2", "ReplaceNetworkAclEntry"),
Action("ec2", "DeleteNetworkAclEntry"),
Action("ec2", "ReplaceNetworkAclAssociation"),
# Reserved, scheduled and dedicated instances
Action("ec2", "CancelReservedInstancesListing"),
Action("ec2", "ModifyReservedInstances"),
Action("ec2", "PurchaseReservedInstancesOffering"),
Action("ec2", "PurchaseHostReservation"),
Action("ec2", "PurchaseScheduledInstances"),
],
Resource=["*"]
),
Statement(
Effect=Deny,
Action=[
Action("*"),
],
Resource=[
GetAtt(developer_role, "Arn"),
"arn:aws:cloudformation:::stack/BaseInfrastructure*",
],
),
Statement(
Effect=Allow,
Action=[
Action("support", "*"),
Action("ec2", "*"),
Action("ecs", "*"),
Action("ecr", "*"),
Action("lambda", "*"),
Action("elasticbeanstalk", "*"),
Action("s3", "*"),
Action("glacier", "*"),
Action("rds", "*"),
Action("dynamodb", "*"),
Action("elasticache", "*"),
Action("redshift", "*"),
Action("route53", "*"),
Action("cloudwatch", "*"),
Action("events", "*"),
Action("logs", "*"),
Action("cloudformation", "*"),
Action("elasticmapreduce", "*"),
Action("datapipeline", "*"),
Action("es", "*"),
Action("kinesis", "*"),
Action("kinesisanalytics", "*"),
Action("firehose", "*"),
Action("sns", "*"),
Action("sqs", "*"),
Action("apigateway", "*"),
Action("autoscaling", "*"),
Action("application-autoscaling", "*")
],
Resource=["*"],
)
],
)
))
admin = Security.create_admin_role("administrator")
dev = Security.create_developer_role("developer")
Security.create_developer_policy(dev)
t = CfTemplate.template.to_json(indent=None)
client = connect('us-east-1')
validate_template(client, t)
__________
You have to create common python file which create CF
common.py
from StringIO import StringIO
from base64 import b64encode
from datetime import datetime
from gzip import GzipFile
from pprint import pprint
from shutil import copyfileobj
from time import time, mktime
from uuid import uuid4
import botocore
from boto3 import Session
from troposphere.ec2 import SecurityGroupRule
def connect(region):
session = Session(region_name=region)
connectors = {
'cloudformation': session.client('cloudformation'),
'iam': session.client('iam'),
'ec2': session.client('ec2'),
's3': session.client('s3')
}
return connectors
def validate_template(aws, template):
response = aws['cloudformation'].validate_template(
TemplateBody=template
)
pprint(response)
def push_cloudformation(aws, template, stack_name, parameters_list=list()):
def create_stack_change(aws, template, stack_name, parameters_list):
response = aws['cloudformation'].create_change_set(
StackName=stack_name,
TemplateBody=template,
ChangeSetName='changeset%s' % (datetime.fromtimestamp(time()).strftime('%Y%m%d%H%M%S')),
Description=str(uuid4()),
Capabilities=[
'CAPABILITY_IAM',
],
Parameters=parameters_list
)
pprint(response)
def create_stack(aws, template, stack_name, parameters_list):
response = aws['cloudformation'].create_stack(
StackName=stack_name,
TemplateBody=template,
Capabilities=[
'CAPABILITY_IAM',
],
OnFailure='DO_NOTHING',
Parameters=parameters_list
)
pprint(response)
def lookup_stack(aws, stackname, ):
try:
response = aws['cloudformation'].describe_stacks(
StackName=stackname,
)
for stack in response.get('Stacks'):
if "PROGRESS" in stack.get('StackStatus'):
raise SystemExit("Stack update in progress")
elif "FAILED" in stack.get('StackStatus'):
raise SystemExit("Stack in failed status")
else:
return ("stack_ready")
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == 'ValidationError':
return ("non_existing_stack")
status = lookup_stack(aws, stack_name)
if status is "non_existing_stack":
print("Creating new stack...")
create_stack(aws, template, stack_name, parameters_list)
elif status is "stack_ready":
print("Creating change set...")
create_stack_change(aws, template, stack_name, parameters_list)
def generate_sg_rules(protocol, low_port, high_port, acl_ips):
acl = []
for ip in acl_ips:
acl.append(SecurityGroupRule(
IpProtocol=protocol,
FromPort=low_port,
ToPort=high_port,
CidrIp=ip,
))
return acl
def get_data_from_stack(region, stack_name, key):
client = connect(region)
response = client['cloudformation'].describe_stacks(
StackName=stack_name,
)
for i in response.get('Stacks'):
for j in i.get('Outputs'):
if j.get('OutputKey') == key:
return j.get('OutputValue')
def prepare_ansible_playbook(file_path):
magicdate = datetime(2016, 1, 1, 2, 15)
gz = StringIO()
with open(file_path, 'rb') as f_in, GzipFile(fileobj=gz, mode="wb", mtime=mktime(magicdate.timetuple())) as f_out:
copyfileobj(f_in, f_out)
gz.seek(0)
gz_b64 = b64encode(gz.read())
return gz_b64