def __init__(self, parameters): super(StackSetRole, self).__init__() self.AdministrationRole = iam.Role( "AdministrationRole", RoleName="AWSCloudFormationStackSetAdministrationRole", Path="/", AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Action=[aws.Action("sts", "AssumeRole")], Effect=aws.Allow, Principal=aws.Principal( "Service", "cloudformation.amazonaws.com" ) ) ], ), Policies=[ iam.Policy( PolicyName="AssumeRole-AWSCloudFormationStackSetExecutionRole", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Action=[aws.Action("sts", "AssumeRole")], Effect=aws.Allow, Resource=["arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole"], ) ] ), ) ] ) self.ExecutionRole = iam.Role( "ExecutionRole", RoleName="AWSCloudFormationStackSetExecutionRole", Path="/", ManagedPolicyArns=["arn:aws:iam::aws:policy/AdministratorAccess"], AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Action=[aws.Action("sts", "AssumeRole")], Effect=aws.Allow, Principal=aws.Principal( "AWS", Ref(parameters.AdministratorAccountId) ) ) ] ) )
def _bind_role(self, t, r): r.Policies.append( iam.Policy( 'codedeploy', PolicyName='codedeploy', PolicyDocument=aws.Policy(Statement=[ aws.Statement( Effect=aws.Allow, Resource=['*'], Action=[ aws.Action('autoscaling', '*'), aws.Action('elasticloadbalancing', 'DescribeLoadBalancers'), # noqa aws.Action('elasticloadbalancing', 'DescribeInstanceHealth'), # noqa aws.Action('elasticloadbalancing', 'RegisterInstancesWithLoadBalancer'), aws.Action('elasticloadbalancing', 'DeregisterInstancesFromLoadBalancer'), aws.Action('ec2', 'Describe*'), aws.Action('ec2', 'TerminateInstances'), aws.Action('tag', 'GetTags'), aws.Action('tag', 'GetResources'), aws.Action('tag', 'GetTagsForResource'), aws.Action('tag', 'GetTagsForResourceList'), aws.Action('lambda', '*') ]), ])))
def _bind_role(self, t, r): brefs = [] for b in self.buckets: bn = b.output_bucket_name() if bn in t.parameters: brefs.append(t.parameters[bn]) else: brefs.append(t.add_parameter(Parameter(bn, Type="String"))) r.Policies.append( iam.Policy( "s3fullaccess", PolicyName="s3fullaccess", PolicyDocument=aws.Policy(Statement=[ aws.Statement( Action=[awacs.aws.Action("s3", "*")], Effect=aws.Allow, Resource=[ Join("", ["arn:aws:s3:::", Ref(i)]) for i in brefs ]), aws.Statement(Action=[awacs.aws.Action("s3", "*")], Effect=aws.Allow, Resource=[ Join("", ["arn:aws:s3:::", Ref(i), "/*"]) for i in brefs ]), ])))
def test_for_all_values(self): c = aws.Condition( aws.ForAllValuesStringLike("dynamodb:requestedAttributes", ["PostDateTime", "Message", "Tags"])) pd = aws.Policy(Statement=[ aws.Statement( Action=[s3.ListBucket], Effect=aws.Allow, Resource=[s3.ARN("myBucket")], Condition=c, ) ]) self.assertEqual( { u'Statement': [{ u'Action': [u's3:ListBucket'], u'Condition': { u'ForAllValues:StringLike': { u'dynamodb:requestedAttributes': [u'PostDateTime', u'Message', u'Tags'] } }, u'Effect': u'Allow', u'Resource': [u'arn:aws:s3:::myBucket'] }] }, json.loads(pd.to_json()))
def _build_template(self, template): t = template if self.principals == "*": principal_title = "*" else: principal_title = "Service" role = t.add_resource( iam.Role(self.name, AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Action=[awacs.sts.AssumeRole], Effect=aws.Allow, Principal=aws.Principal( principal_title, self.principals)) ]), Path="/", Policies=[], ManagedPolicyArns=[])) for p in self.policies: p._bind_role(t, role) for m in self.managed_policies: role.ManagedPolicyArns.append(m) t.add_output([ Output('{}Role'.format(self.name), Value=Ref(role)), Output('{}RoleArn'.format(self.name), Value=GetAtt(role, "Arn")) ]) return t
def _bind_role(self, t, r): r.Policies.append( iam.Policy('sqsall', PolicyName='sqsall', PolicyDocument=aws.Policy(Statement=[ aws.Statement(Action=[awacs.aws.Action("sqs", "*")], Effect=aws.Allow, Resource=["*"]) ])))
def _bind_role(self, template, role): role.Policies.append( iam.Policy('ec2fullaccess', PolicyName='ec2fullaccess', PolicyDocument=aws.Policy(Statement=[ aws.Statement(Action=[awacs.aws.Action("ec2", "*")], Effect=aws.Allow, Resource=["*"]) ])))
def _service_assume_role(service: str) -> AWS.Policy: """Build and return the IAM AssumeRolePolicy for use in service roles.""" return AWS.Policy(Statement=[ AWS.Statement( Effect=AWS.Allow, Action=[STS.AssumeRole], Principal=AWS.Principal("Service", ["{}.amazonaws.com".format(service)]), ) ])
def generate_role_template( command: str, actions: list, role_name: str, path: str, assuming_account_id: str, assuming_resource: str, output_format: str, ) -> str: t = troposphere.Template() t.description = f"Role used to run the {command} command" t.add_resource( iam.Role( title="role", RoleName=role_name, Path=path, Policies=[ iam.Policy( PolicyName=f"{command}-permissions", PolicyDocument=aws.PolicyDocument( Version="2012-10-17", Id=f"{command}-permissions", Statement=[ aws.Statement( Sid="1", Effect=aws.Allow, Action=actions, Resource=["*"], ), ], ), ) ], AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Id="AllowAssume", Statement=[ aws.Statement( Sid="1", Effect=aws.Allow, Principal=aws.Principal("AWS", [ IAM_ARN(assuming_resource, "", assuming_account_id) ]), Action=[awacs_sts.AssumeRole], ), ], ), )) if output_format == "json": return t.to_json() else: return t.to_yaml()
def _bind_role(self, t, r): r.Policies.append( iam.Policy('cloudwatch', PolicyName='cloudwatch', PolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Resource=['*'], Action=[ aws.Action("logs", "*"), ]) ])))
def generate_role_template( command: str, actions: list, role_name: str, path: str, assuming_account_id: str, assuming_resource: str, additional_statements: list = [], ) -> troposphere.Template: t = troposphere.Template() t.description = f"Role used to run the {command} command" role = iam.Role( title="role", RoleName=role_name, Path=path, Policies=[ iam.Policy( PolicyName=f"{command}-permissions", PolicyDocument=aws.PolicyDocument( Version="2012-10-17", Id=f"{command}-permissions", Statement=[ aws.Statement(Sid="1", Effect=aws.Allow, Action=actions, Resource=["*"]) ] + additional_statements, ), ) ], AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Id="AllowAssume", Statement=[ aws.Statement( Sid="1", Effect=aws.Allow, Principal=aws.Principal( "AWS", [IAM_ARN(assuming_resource, "", assuming_account_id)]), Action=[awacs_sts.AssumeRole], ) ], ), ) t.add_resource(role) t.add_output(troposphere.Output("RoleName", Value=troposphere.Ref(role))) t.add_output( troposphere.Output("RoleArn", Value=troposphere.GetAtt(role, "Arn"))) return t
def build_subscription(self, t, topic): policy = t.add_resource( iam.Role( "{}SlackSNSRole".format(self.name), AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Action=[awacs.sts.AssumeRole], Effect=aws.Allow, Principal=aws.Principal( "Service", ["lambda.amazonaws.com"])) ]), Path="/", Policies=[ iam.Policy( PolicyName='snspublic', PolicyDocument=aws.PolicyDocument(Statement=[ aws.Statement(Effect=aws.Allow, Action=[ awacs.sns.Publish, awacs.logs.PutLogEvents, awacs.logs.CreateLogGroup, awacs.logs.CreateLogStream, ], Resource=["*"]) ])) ], ManagedPolicyArns=[ # "arn:aws:iam::aws:policy/AdministratorAccess" ])) code = ["import sys"] # make lambda function fn = t.add_resource( awslambda.Function('{}SlackTopicFN'.format(self.name), Handler='index.handle', Runtime='python3.6', Role=GetAtt(policy, "Arn"), Code=awslambda.Code(ZipFile=Join("", code)))) t.add_resource( awslambda.Permission('{}LambdaPerm'.format(self.name), Action='lambda:InvokeFunction', FunctionName=GetAtt(fn, "Arn"), SourceArn=Ref(topic), Principal="sns.amazonaws.com")) return ("lambda", GetAtt(fn, "Arn"))
def _bind_role(self, t, r): brefs = [] for b in self.buckets: bn = b.output_bucket_name() if bn in t.parameters: brefs.append(t.parameter[bn]) else: brefs.append(t.add_parameter(Parameter(bn, Type='String'))) r.Policies.append( iam.Policy( 's3readaccess', PolicyName='s3readaccess', PolicyDocument=aws.Policy(Statement=[ aws.Statement( Effect=aws.Allow, Action=[ awacs.aws.Action('s3', 'GetObject*'), awacs.aws.Action('s3', 'ListAllMyBuckets'), awacs.aws.Action('s3', 'GetObject'), awacs.aws.Action('s3', 'ListBucket'), awacs.aws.Action('s3', 'ListBucketVersions'), ], Resource=[ Join("", ["arn:aws:s3:::", Ref(i), "/*"]) for i in brefs ]), aws.Statement( Effect=aws.Allow, Action=[ awacs.aws.Action('s3', 'GetObject*'), awacs.aws.Action('s3', 'ListAllMyBuckets'), awacs.aws.Action('s3', 'GetObject'), awacs.aws.Action('s3', 'ListBucket'), awacs.aws.Action('s3', 'ListBucketVersions'), ], Resource=[ Join("", ["arn:aws:s3:::", Ref(i), "*"]) for i in brefs ]) ])))
def _bind_role(self, t, r): r.Policies.append( iam.Policy( 'DynamoScaleRolePolicy', PolicyName='DynamoScaleRolePolicy', PolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[ aws.Action("dynamodb", "DescribeTable"), aws.Action("dynamodb", "UpdateTable"), ], Resource=["*"]), aws.Statement( Effect=aws.Allow, Action=[ aws.Action("cloudwatch", "PutMetricAlarm"), aws.Action("cloudwatch", "DescribeAlarms"), aws.Action("cloudwatch", "GetMetricStatistics"), aws.Action("cloudwatch", "SetAlarmState"), aws.Action("cloudwatch", "DeleteAlarms"), ], Resource=["*"]), ])))
def __init__(self, parameters, groups): """ :type parameters Parameters :type groups Groups """ super(RolesAndPolicies, self).__init__() self.EC2Baseline = iam.Role( "EC2Baseline", AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement(Action=[aws.Action("sts", "AssumeRole")], Effect=aws.Allow, Principal=aws.Principal( "Service", "ec2.amazonaws.com")) ], )) self.LambdaBasicExecution = iam.Role( "LambdaBasicExecution", AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement(Action=[aws.Action("sts", "AssumeRole")], Effect=aws.Allow, Principal=aws.Principal( "Service", "lambda.amazonaws.com")) ], ), ) self.ECSClusterServiceRole = iam.Role( "ECSClusterServiceRole", Policies=[ iam.Policy( PolicyName=Join("", [Ref(AWS_STACK_NAME), "-ecs-service"]), PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Action=[ aws.Action( "ec2", "AuthorizeSecurityGroupIngress"), aws.Action("ec2", "Describe*"), aws.Action( "elasticloadbalancing", "DeregisterInstancesFromLoadBalancer"), aws.Action("elasticloadbalancing", "Describe*"), aws.Action( "elasticloadbalancing", "RegisterInstancesWithLoadBalancer"), aws.Action("elasticloadbalancing", "DeregisterTargets"), aws.Action("elasticloadbalancing", "DescribeTargetGroups" ), # todo: remove aws.Action("elasticloadbalancing", "DescribeTargetHealth" ), # todo: remove aws.Action("elasticloadbalancing", "RegisterTargets"), ], Resource=["*"], Effect=aws.Allow) ])) ], AssumeRolePolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement(Action=[aws.Action("sts", "AssumeRole")], Effect=aws.Allow, Principal=aws.Principal( "Service", "ecs.amazonaws.com")) ], )) self.ForceMFA = iam.ManagedPolicy( "ForceMFA", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement(Sid="AllowAllUsersToListAccounts", Action=[ aws.Action("iam", "ListAccountAliases"), aws.Action("iam", "ListUsers"), aws.Action("iam", "GetAccountSummary"), ], Resource=["*"], Effect=aws.Allow), aws.Statement( Sid= "AllowIndividualUserToSeeAndManageOnlyTheirOwnAccountInformation", Action=[ aws.Action("iam", "ChangePassword"), aws.Action("iam", "CreateAccessKey"), aws.Action("iam", "CreateLoginProfile"), aws.Action("iam", "DeleteAccessKey"), aws.Action("iam", "DeleteLoginProfile"), aws.Action("iam", "GetAccountPasswordPolicy"), aws.Action("iam", "GetLoginProfile"), aws.Action("iam", "ListAccessKeys"), aws.Action("iam", "UpdateAccessKey"), aws.Action("iam", "UpdateLoginProfile"), aws.Action("iam", "ListSigningCertificates"), aws.Action("iam", "DeleteSigningCertificate"), aws.Action("iam", "UpdateSigningCertificate"), aws.Action("iam", "UploadSigningCertificate"), aws.Action("iam", "ListSSHPublicKeys"), aws.Action("iam", "GetSSHPublicKey"), aws.Action("iam", "DeleteSSHPublicKey"), aws.Action("iam", "UpdateSSHPublicKey"), aws.Action("iam", "UploadSSHPublicKey"), ], Resource=[ Join("", [ "arn:aws:iam::", AccountId, ":user/${aws:username}" ]) ], Effect=aws.Allow), aws.Statement( Sid="AllowIndividualUserToListOnlyTheirOwnMFA", Action=[ aws.Action("iam", "ListVirtualMFADevices"), aws.Action("iam", "ListMFADevices"), ], Resource=[ Join("", ["arn:aws:iam::", AccountId, ":mfa/*"]), Join("", [ "arn:aws:iam::", AccountId, ":user/${aws:username}" ]) ], Effect=aws.Allow), aws.Statement( Sid= "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA", Action=[ aws.Action("iam", "DeactivateMFADevice"), ], Condition=aws.Condition( aws.Bool("aws:MultiFactorAuthPresent", True)), Resource=[ Join("", [ "arn:aws:iam::", AccountId, ":mfa/${aws:username}" ]), Join("", [ "arn:aws:iam::", AccountId, ":user/${aws:username}" ]) ], Effect=aws.Allow), aws.Statement( Sid="BlockAnyAccessOtherThanAboveUnlessSignedInWithMFA", Condition=aws.Condition( aws.BoolIfExists("aws:MultiFactorAuthPresent", False)), NotAction=[ aws.Action("iam", "*"), ], Resource=["*"], Effect=aws.Deny), ], ), Description="Forces MFA usage on all users in assigned groups", Groups=[ Ref(groups.AWSEngineers.title), Ref(groups.ReadOnlyUsers.title), ], ) self.FullAdministrator = iam.ManagedPolicy( "FullAdministrator", PolicyDocument=aws.Policy(Version="2012-10-17", Statement=[ aws.Statement( Action=[aws.Action("*")], Resource=["*"], Effect=aws.Allow) ]), Description="Allows full access to all AWS", Groups=[ Ref(groups.AWSEngineers.title), ], ) self.CIDeploymentPolicy = iam.ManagedPolicy( "CIDeploymentPolicy", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement(Action=[ aws.Action("cloudformation", "DescribeStacks"), aws.Action("cloudformation", "DescribeStackEvents"), aws.Action("cloudformation", "DescribeStackResources"), aws.Action("cloudformation", "DescribeChangeSet"), aws.Action("cloudformation", "GetTemplate"), aws.Action("cloudformation", "GetTemplateSummary"), aws.Action("cloudformation", "List*"), aws.Action("cloudformation", "PreviewStackUpdate"), aws.Action("cloudformation", "CancelUpdateStack"), aws.Action("cloudformation", "ContinueUpdateRollback"), aws.Action("cloudformation", "CreateChangeSet"), aws.Action("cloudformation", "CreateStack"), aws.Action("cloudformation", "CreateUploadBucket"), aws.Action("cloudformation", "ExecuteChangeSet"), aws.Action("cloudformation", "SignalResource"), aws.Action("cloudformation", "UpdateStack"), aws.Action("cloudformation", "ValidateTemplate"), aws.Action("cloudformation", "SetStackPolicy"), aws.Action("ecs", "Describe*"), aws.Action("ecs", "RegisterTaskDefinition"), aws.Action("ecs", "UpdateService"), aws.Action("ecs", "List*"), aws.Action("ecs", "DeregisterTaskDefinition"), aws.Action("ecs", "DiscoverPollEndpoint"), aws.Action("ecs", "Poll"), aws.Action("ecr", "DescribeRepositories"), aws.Action("ecr", "ListImages"), aws.Action("ecr", "BatchCheckLayerAvailability"), aws.Action("ecr", "BatchGetImage"), aws.Action("ecr", "GetAuthorizationToken"), aws.Action("ecr", "GetDownloadUrlForLayer"), aws.Action("ecr", "GetRepositoryPolicy"), aws.Action("ecr", "CompleteLayerUpload"), aws.Action("ecr", "InitiateLayerUpload"), aws.Action("ecr", "PutImage"), aws.Action("ecr", "UploadLayerPart"), aws.Action("logs", "Describe*"), ], Resource=["*"], Effect=aws.Allow) ]), Description="Allows access to cloudformation for CircleCI", Groups=[ Ref(groups.CIDeploymentServices.title), ], ) self.S3Administrator = iam.ManagedPolicy( "S3Administrator", PolicyDocument=aws.Policy(Version="2012-10-17", Statement=[ aws.Statement(Action=[ aws.Action("s3", "*"), ], Resource=["*"], Effect=aws.Allow) ]), Description="Allows full management of S3", Groups=[Ref(groups.AWSEngineers.title)], Users=[], ) self.LoggingAndMonitoring = iam.ManagedPolicy( "LoggingAndMonitoring", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement(Action=[ aws.Action("cloudwatch", "GetMetricStatistics"), aws.Action("cloudwatch", "ListMetrics"), aws.Action("cloudwatch", "PutMetricData"), aws.Action("ec2", "DescribeTags"), aws.Action("logs", "CreateLogGroup"), aws.Action("logs", "CreateLogStream"), aws.Action("logs", "DescribeLogGroups"), aws.Action("logs", "DescribeLogStreams"), aws.Action("logs", "PutLogEvents"), aws.Action("sns", "Publish"), ], Resource=["*"], Effect=aws.Allow) ]), Description= "Allows ingestion of logs and metrics into CloudWatch and publishing to SNS topics", Roles=[Ref(self.EC2Baseline)], )
def add_resources(self): self.runner_ssm_role = self.template.add_resource( Role( "RunnerSsmRole", Path="/", ManagedPolicyArns=[ "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM" ], AssumeRolePolicyDocument=aws.Policy(Statement=[ Statement( Action=[sts.AssumeRole], Effect=Allow, Principal=Principal("Service", ["ec2.amazonaws.com"]), ) ]), )) self.runner_ssm_instanceprofile = self.template.add_resource( InstanceProfile("RunnerSsmInstanceProfile", Path="/", Roles=[Ref(self.runner_ssm_role)])) self.runner_launch_config = self.template.add_resource( LaunchConfiguration( "RunnerLaunchConfiguration", UserData=Base64( Join( "", [ "#!/bin/bash\n", "#####install ssm######\n", "yum install -y amazon-ssm-agent\n", "systemctl enable amazon-ssm-agent\n", "systemctl start amazon-ssm-agent\n", "####install docker####\n", "yum install -y docker\n", "systemctl enable docker\n", "systemctl start docker\n", "####install runner####\n", "yum install -y wget\n", "wget -O /usr/local/bin/gitlab-runner ", "https://gitlab-runner-downloads.s3.amazonaws.com/v", Ref(self.runner_version), "/binaries/gitlab-runner-linux-amd64\n", "ln -s /usr/local/bin/gitlab-runner ", "/usr/bin/gitlab-runner\n", "chmod +x /usr/local/bin/gitlab-runner\n", "useradd --comment 'GitLab Runner' ", "--create-home gitlab-runner --shell /bin/bash\n", "/usr/local/bin/gitlab-runner install ", "--user=gitlab-runner " "--working-directory=/home/gitlab-runner\n", "systemctl enable gitlab-runner\n", "systemctl start gitlab-runner\n", "####register runner####\n", "gitlab-runner register ", "--config=/etc/gitlab-runner/config.toml ", "--request-concurrency=", Ref(self.runner_job_concurrency), " ", "--tag-list=", Ref(self.runner_tag_list), " ", "--non-interactive ", "--registration-token=", Ref(self.runner_register_token), " ", "--run-untagged=true ", "--locked=false ", "--url=", Ref(self.runner_gitlab_url), " ", "--executor=docker ", "--docker-image=alpine:latest ", "--docker-privileged=true\n", "####create unregister script####\n", "TOKEN=$(gitlab-runner list 2>&1 | grep Executor | ", "awk '{ print $4 }' | awk -F= '{ print $2 }')\n", "URL=$(gitlab-runner list 2>&1 | grep Executor | ", "awk '{ print $5 }' | awk -F= '{ print $2 }')\n", "echo gitlab-runner unregister ", "--url $URL --token $TOKEN > /unregister.sh\n", "chmod +x /unregister.sh", ], )), ImageId=Ref(self.runner_ami_id), KeyName=Ref(self.runner_key_pair), BlockDeviceMappings=[ BlockDeviceMapping( DeviceName="/dev/xvda", Ebs=EBSBlockDevice( VolumeSize=Ref(self.runner_volume_size)), ) ], SecurityGroups=[Ref(self.runner_security_group)], InstanceType=Ref(self.runner_server_instance_type), IamInstanceProfile=GetAtt(self.runner_ssm_instanceprofile, "Arn"), )) self.runner_autoscaling_group = self.template.add_resource( AutoScalingGroup( "RunnerAutoscalingGroup", DesiredCapacity=Ref(self.runner_desired_count), LaunchConfigurationName=Ref(self.runner_launch_config), MinSize=Ref(self.runner_min_count), MaxSize=Ref(self.runner_max_count), VPCZoneIdentifier=Split(",", Ref(self.runner_subnets)), Tags=[Tag("Name", "gitlab-runner-created-by-asg", True)], ))
# S3 bucket s3bucket = t.add_resource( s3.Bucket( "StrongjobsS3Bucket", BucketName="strongjobs", AccessControl=s3.Private, )) # Access management things serviceRole = t.add_resource( iam.Role("StrongjobsServiceRole", AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[sts.AssumeRole], Principal=aws.Principal( "Service", ["codedeploy.amazonaws.com"])), aws.Statement(Effect=aws.Allow, Action=[sts.AssumeRole], Principal=aws.Principal("Service", ["ec2.amazonaws.com"])), ], ), ManagedPolicyArns=[ "arn:aws:iam::aws:policy/AmazonS3FullAccess", "arn:aws:iam::aws:policy/service-role/" "AWSCodeDeployRole" ])) IAMInstanceProfile = t.add_resource( iam.InstanceProfile("StrongjobsInstanceProfile", Roles=[Ref(serviceRole)])) # Launch configuration launchConfiguration = t.add_resource( autoscaling.LaunchConfiguration(
def main(): t = Template("A template to create a load balanced autoscaled Web flask deployment using ansible.") addMapping(t) ### VPC CONFIGURATION ### vpc = ec2.VPC( "MainVPC", CidrBlock="10.1.0.0/16" ) t.add_resource(vpc) vpc_id = Ref(vpc) subnet_1 = ec2.Subnet( "WebAppSubnet1", t, AvailabilityZone="us-east-1a", CidrBlock="10.1.0.0/24", MapPublicIpOnLaunch=True, VpcId=vpc_id, ) subnet_1_id = Ref(subnet_1) subnet_2 = ec2.Subnet( "WebAppSubnet2", t, AvailabilityZone="us-east-1b", CidrBlock="10.1.1.0/24", MapPublicIpOnLaunch=True, VpcId=vpc_id, ) subnet_2_id = Ref(subnet_2) ### NETWORKING ### igw = ec2.InternetGateway("internetGateway", t) gateway_to_internet = ec2.VPCGatewayAttachment( "GatewayToInternet", t, VpcId=vpc_id, InternetGatewayId=Ref(igw) ) route_table = ec2.RouteTable( "subnetRouteTable", t, VpcId=vpc_id ) route_table_id = Ref(route_table) internet_route = ec2.Route( "routeToInternet", t, DependsOn=gateway_to_internet, DestinationCidrBlock="0.0.0.0/0", GatewayId=Ref(igw), RouteTableId=route_table_id ) subnet_1_route_assoc = ec2.SubnetRouteTableAssociation( "Subnet1RouteAssociation", t, RouteTableId=route_table_id, SubnetId=Ref(subnet_1) ) subnet_2_route_assoc = ec2.SubnetRouteTableAssociation( "Subnet2RouteAssociation", t, RouteTableId=route_table_id, SubnetId=Ref(subnet_2) ) http_ingress = { "CidrIp": "0.0.0.0/0", "Description": "Allow HTTP traffic in from internet.", "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, } ssh_ingress = { "CidrIp": "0.0.0.0/0", "Description": "Allow SSH traffic in from internet.", "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, } elb_sg = ec2.SecurityGroup( "elbSecurityGroup", t, GroupName="WebGroup", GroupDescription="Allow web traffic in from internet to ELB", VpcId=vpc_id, SecurityGroupIngress=[ http_ingress ]) ssh_sg = ec2.SecurityGroup( "sshSecurityGroup", t, GroupName="SSHGroup", GroupDescription="Allow SSH traffic in from internet", VpcId=vpc_id, SecurityGroupIngress=[ ssh_ingress ] ) elb_sg_id = Ref(elb_sg) ssh_sg_id = Ref(ssh_sg) autoscale_ingress = { "SourceSecurityGroupId": elb_sg_id, "Description": "Allow web traffic in from ELB", "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80 } autoscale_sg = ec2.SecurityGroup( "WebAutoscaleSG", t, GroupName="AutoscaleGroup", GroupDescription="Allow web traffic in from elb on port 80", VpcId=vpc_id, SecurityGroupIngress=[ autoscale_ingress ] ) autoscale_sg_id = Ref(autoscale_sg) # BUCKETS app_bucket = s3.Bucket( "CodeDeployApplicationBucket", t, ) ### LOAD BALANCING ### Web_elb = elb.LoadBalancer( "WebElb", t, Name="WebElb", # TODO: Fix for name conflict Subnets=[subnet_1_id, subnet_2_id], SecurityGroups=[elb_sg_id] ) Web_target_group = elb.TargetGroup( "WebTargetGroup", t, DependsOn=Web_elb, HealthCheckPath="/health", HealthCheckPort=80, HealthCheckProtocol="HTTP", Matcher=elb.Matcher(HttpCode="200"), Name="NginxTargetGroup", Port=80, Protocol="HTTP", VpcId=vpc_id ) Web_listener = elb.Listener( "WebListener", t, LoadBalancerArn=Ref(Web_elb), DefaultActions=[ elb.Action("forwardAction", TargetGroupArn=Ref(Web_target_group), Type="forward" ) ], Port=80, Protocol="HTTP" ) ### AUTOSCALING ### # Everything after sudo -u ubuntu is one command # The sudo command is required to properly set file permissions when # running the ansible script as it assumes running from non root user lc_user_data = Base64(Join("\n", [ "#!/bin/bash", "apt-add-repository -y ppa:ansible/ansible", "apt-get update && sudo apt-get -y upgrade", "apt-get -y install git", "apt-get -y install ansible", "cd /home/ubuntu/", "sudo -H -u ubuntu bash -c '" "export LC_ALL=C.UTF-8 && " "export LANG=C.UTF-8 && " "ansible-pull -U https://github.com/DameonSmith/aws-meetup-ansible.git --extra-vars \"user=ubuntu\"'" ])) web_instance_role = iam.Role( "webInstanceCodeDeployRole", t, AssumeRolePolicyDocument={ 'Statement': [{ 'Effect': 'Allow', 'Principal': { 'Service': 'ec2.amazonaws.com' }, 'Action': 'sts:AssumeRole' }] }, Policies=[ iam.Policy( PolicyName="CodeDeployS3Policy", PolicyDocument=aws.Policy( Version='2012-10-17', Statement=[ aws.Statement( Sid='CodeDeployS3', Effect=aws.Allow, Action=[ aws_s3.PutObject, aws_s3.GetObject, aws_s3.GetObjectVersion, aws_s3.DeleteObject, aws_s3.ListObjects, aws_s3.ListBucket, aws_s3.ListBucketVersions, aws_s3.ListAllMyBuckets, aws_s3.ListMultipartUploadParts, aws_s3.ListBucketMultipartUploads, aws_s3.ListBucketByTags, ], Resource=[ GetAtt(app_bucket, 'Arn'), Join('', [ GetAtt(app_bucket, 'Arn'), '/*', ]), "arn:aws:s3:::aws-codedeploy-us-east-2/*", "arn:aws:s3:::aws-codedeploy-us-east-1/*", "arn:aws:s3:::aws-codedeploy-us-west-1/*", "arn:aws:s3:::aws-codedeploy-us-west-2/*", "arn:aws:s3:::aws-codedeploy-ca-central-1/*", "arn:aws:s3:::aws-codedeploy-eu-west-1/*", "arn:aws:s3:::aws-codedeploy-eu-west-2/*", "arn:aws:s3:::aws-codedeploy-eu-west-3/*", "arn:aws:s3:::aws-codedeploy-eu-central-1/*", "arn:aws:s3:::aws-codedeploy-ap-northeast-1/*", "arn:aws:s3:::aws-codedeploy-ap-northeast-2/*", "arn:aws:s3:::aws-codedeploy-ap-southeast-1/*", "arn:aws:s3:::aws-codedeploy-ap-southeast-2/*", "arn:aws:s3:::aws-codedeploy-ap-south-1/*", "arn:aws:s3:::aws-codedeploy-sa-east-1/*", ] ) ] ) ) ] ) web_instance_profile = iam.InstanceProfile( "webInstanceProfile", t, Path='/', Roles=[Ref(web_instance_role)], ) Web_launch_config = autoscaling.LaunchConfiguration( "webLaunchConfig", t, ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"), # TODO: Remove magic string SecurityGroups=[ssh_sg_id, autoscale_sg_id], IamInstanceProfile=Ref(web_instance_profile), InstanceType="t2.micro", BlockDeviceMappings= [{ "DeviceName": "/dev/sdk", "Ebs": {"VolumeSize": "10"} }], UserData= lc_user_data, KeyName="advanced-cfn", ) Web_autoscaler = autoscaling.AutoScalingGroup( "WebAutoScaler", t, LaunchConfigurationName=Ref(Web_launch_config), MinSize="2", # TODO: Change to parameter MaxSize="2", VPCZoneIdentifier=[subnet_2_id, subnet_1_id], TargetGroupARNs= [Ref(Web_target_group)] ) t.add_output([ Output( "ALBDNS", Description="The DNS name for the application load balancer.", Value=GetAtt(Web_elb, "DNSName") ) ]) # DEVTOOLS CONFIG codebuild_service_role = iam.Role( "CMSCodeBuildServiceRole", t, AssumeRolePolicyDocument={ 'Statement': [{ 'Effect': 'Allow', 'Principal': { 'Service': ['codebuild.amazonaws.com'] }, 'Action': ['sts:AssumeRole'] }] }, Policies=[ iam.Policy( PolicyName="CloudWatchLogsPolicy", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Sid='logs', Effect=aws.Allow, Action=[ aws_logs.CreateLogGroup, aws_logs.CreateLogStream, aws_logs.PutLogEvents ], Resource=['*'] ) ] ) ), iam.Policy( PolicyName="s3AccessPolicy", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Sid='codebuilder', Effect=aws.Allow, Action=[ aws_s3.PutObject, aws_s3.GetObject, aws_s3.GetObjectVersion, aws_s3.DeleteObject ], Resource=[ GetAtt(app_bucket, 'Arn'), Join('', [ GetAtt(app_bucket, 'Arn'), '/*', ]) ] ) ] ) ) ] ) github_repo = Parameter( "GithubRepoLink", Description="Name of the repository you wish to connect to codebuild.", Type="String" ) artifact_key = Parameter( "ArtifactKey", Description="The key for the artifact that codebuild creates.", Type="String" ) t.add_parameter(github_repo) t.add_parameter(artifact_key) cms_code_build_project = codebuild.Project( "CMSBuild", t, Name="CMS-Build", Artifacts=codebuild.Artifacts( Location=Ref(app_bucket), Name=Ref(artifact_key), NamespaceType="BUILD_ID", Type="S3", Packaging="ZIP" ), Description="Code build for CMS", Environment=codebuild.Environment( ComputeType="BUILD_GENERAL1_SMALL", Image="aws/codebuild/python:3.6.5", Type="LINUX_CONTAINER", ), ServiceRole=GetAtt(codebuild_service_role, 'Arn'), Source=codebuild.Source( "CMSSourceCode", Auth=codebuild.SourceAuth( "GitHubAuth", Type="OAUTH" ), Location=Ref(github_repo), Type="GITHUB" ), Triggers=codebuild.ProjectTriggers( Webhook=True ) ) codedeploy_service_role = iam.Role( "CMSDeploymentGroupServiceRole", t, AssumeRolePolicyDocument={ 'Statement': [{ 'Effect': 'Allow', 'Principal': { 'Service': ['codedeploy.amazonaws.com'] }, 'Action': ['sts:AssumeRole'] }] }, Policies=[ iam.Policy( PolicyName="CloudWatchLogsPolicy", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Sid='logs', Effect=aws.Allow, Action=[ aws_logs.CreateLogGroup, aws_logs.CreateLogStream, aws_logs.PutLogEvents ], Resource=['*'] ) ] ) ), iam.Policy( PolicyName="s3AccessPolicy", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Sid='codebuilder', Effect=aws.Allow, Action=[ aws_s3.PutObject, aws_s3.GetObject, aws_s3.GetObjectVersion, aws_s3.DeleteObject ], Resource=[ GetAtt(app_bucket, 'Arn'), Join('', [ GetAtt(app_bucket, 'Arn'), '/*' ]) ] ) ] ) ), iam.Policy( PolicyName="autoscalingAccess", PolicyDocument=aws.Policy( Version="2012-10-17", Statement=[ aws.Statement( Sid='codebuilder', Effect=aws.Allow, Action=[ aws.Action('autoscaling', '*'), aws.Action('elasticloadbalancing', '*') ], Resource=[ '*' ] ) ] ) ) ] ) cms_codedeploy_application = codedeploy.Application( "CMSCodeDeployApplication", t, ) cms_deployment_group = codedeploy.DeploymentGroup( "CMSDeploymentGroup", t, DependsOn=[cms_codedeploy_application], ApplicationName=Ref(cms_codedeploy_application), AutoScalingGroups=[Ref(Web_autoscaler)], LoadBalancerInfo=codedeploy.LoadBalancerInfo( "CodeDeployLBInfo", TargetGroupInfoList=[ codedeploy.TargetGroupInfoList( "WebTargetGroup", Name=GetAtt(Web_target_group, "TargetGroupName") ) ] ), ServiceRoleArn=GetAtt(codedeploy_service_role, 'Arn') ) print(t.to_yaml())
Description="Name of the bucket where lambda function sources is stored" )) param_lambda_file_name = template.add_parameter( Parameter( "LambdaFileName", Type="String", Description= "Name of the ZIP file with lambda function sources inside S3 bucket")) lambda_role = template.add_resource( iam.Role( "LambaRole", AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[sts.AssumeRole], Principal=aws.Principal("Service", ["lambda.amazonaws.com"])) ]), Policies=[ iam.Policy( PolicyName="LambdaPolicy", PolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[ aws.Action("logs", "CreateLogGroup"), aws.Action("logs", "CreateLogStream"), aws.Action("logs", "PutLogEvents"), ], Resource=["arn:aws:logs:*:*:*"]) ])) ]))
])) event = t.add_resource( events.Rule("EventsRule", Condition="IsMaster", EventPattern={"source": ["aws.guardduty"]}, State="ENABLED", Targets=[events.Target( Arn=Ref(snstopic), Id="sns", )])) # Allow events to send notifications to SNS t.add_resource( sns.TopicPolicy( "SNSTopicPolicy", Condition="IsMaster", PolicyDocument=aws.Policy(Statement=[ aws.Statement( Effect=aws.Allow, Action=[ aws.Action("sns", "Publish"), ], Principal=aws.Principal("Service", "events.amazonaws.com"), Resource=[Ref(snstopic)], ), ]), Topics=[Ref(snstopic)])) print(t.to_json())
"default": "Name of S3 bucket" }, "SourceZipParameter": { "default": "Name of ZIP file" }, } } }) # Role for Lambda backup_rds_role = template.add_resource( iam.Role( "LambdaBackupRDSRole", AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[sts.AssumeRole], Principal=aws.Principal("Service", ["lambda.amazonaws.com"])) ]), Policies=[ iam.Policy( "LambdaBackupRDSPolicy", PolicyName="AccessToRDSAndLogs", PolicyDocument=aws.Policy(Statement=[ aws.Statement( Effect=aws.Allow, Action=[ aws.Action('rds', 'DescribeDbSnapshots'), aws.Action('rds', 'CopyDbSnapshot'), aws.Action('rds', 'DeleteDbSnapshot'), aws.Action('rds', 'DeleteDbClusterSnapshot'), aws.Action('rds', 'DescribeDbClusters'),
"default": "Name of S3 bucket" }, "SourceZipParameter": { "default": "Name of ZIP file" }, } } }) # Role for Lambda lambda_role = template.add_resource( iam.Role( "LambdaRole", AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[sts.AssumeRole], Principal=aws.Principal("Service", ["lambda.amazonaws.com"])) ]), Policies=[ iam.Policy( "LambdaBackupRDSPolicy", PolicyName="AccessToEC2Snapshots", PolicyDocument=aws.Policy(Statement=[ aws.Statement( Effect=aws.Allow, Action=[ aws.Action("ec2", "Describe*"), aws.Action("ec2", "CreateSnapshot"), aws.Action("ec2", "DeleteSnapshot"), aws.Action("ec2", "CreateTags"), aws.Action("ec2", "ModifySnapshotAttribute"),
def _bind_role(self, template, role): role.Policies.append( iam.Policy(self.name, PolicyName=self.name, PolicyDocument=aws.Policy(Statement=self.statements)))
def __init__(self, parameters, vpc, loadbalancer): """ :type parameters Parameters :type vpc VPC :type loadbalancer LoadBalancer """ super(EC2, self).__init__() # Ec2 instance self.instance_role = iam.Role( "InstanceRole", AssumeRolePolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[sts.AssumeRole], Principal=aws.Principal("Service", ["ec2.amazonaws.com"])) ]), Path="/", ) self.instance_role_policy = iam.PolicyType( "InstanceRolePolicy", PolicyName=Join("-", [Ref("AWS::StackName"), "instance-policy"]), PolicyDocument=aws.Policy(Statement=[ aws.Statement(Effect=aws.Allow, Action=[ aws.Action("logs", "CreateLogGroup"), aws.Action("logs", "CreateLogStream"), aws.Action("logs", "PutLogEvents"), aws.Action("logs", "DescribeLogStreams"), ], Resource=["arn:aws:logs:*:*:*"]) ]), Roles=[Ref(self.instance_role)]) self.instance_profile = iam.InstanceProfile( "InstanceProfile", Path="/", Roles=[Ref(self.instance_role)]) self.launch_configuration = autoscaling.LaunchConfiguration( "LaunchConfiguration", ImageId=FindInMap("AMIMap", Ref(AWS_REGION), "AMI"), InstanceType=Ref(parameters.ec2_instance_type), KeyName=Ref(parameters.key_pair), InstanceMonitoring=True, SecurityGroups=[ GetAtt(loadbalancer.instance_security_group, "GroupId"), ], IamInstanceProfile=Ref(self.instance_profile), ) self.auto_scaling_group = autoscaling.AutoScalingGroup( "AutoScalingGroup", LaunchConfigurationName=Ref(self.launch_configuration), MinSize=1, DesiredCapacity=1, MaxSize=10, HealthCheckType='ELB', HealthCheckGracePeriod=300, VPCZoneIdentifier=[ Ref(vpc.public_subnet_1), Ref(vpc.public_subnet_2) ], LoadBalancerNames=[Ref(loadbalancer.load_balancer)], Tags=[autoscaling.Tag("Name", Ref("AWS::StackName"), True)], UpdatePolicy=policies.UpdatePolicy( AutoScalingRollingUpdate=policies.AutoScalingRollingUpdate( PauseTime="PT30S", MinInstancesInService=1, MaxBatchSize=10, WaitOnResourceSignals=False)), TerminationPolicies=[ 'OldestLaunchConfiguration', 'ClosestToNextInstanceHour', 'Default' ], MetricsCollection=[ autoscaling.MetricsCollection(Granularity="1Minute") ]) self.scale_up_policy = autoscaling.ScalingPolicy( "ScaleUPPolicy", AdjustmentType='ChangeInCapacity', AutoScalingGroupName=Ref(self.auto_scaling_group), PolicyType='StepScaling', MetricAggregationType='Average', StepAdjustments=[ autoscaling.StepAdjustments(MetricIntervalLowerBound=0, ScalingAdjustment=1) ], ) self.scale_down_policy = autoscaling.ScalingPolicy( "ScaleDOWNPolicy", AdjustmentType='ChangeInCapacity', AutoScalingGroupName=Ref(self.auto_scaling_group), PolicyType='StepScaling', MetricAggregationType='Average', StepAdjustments=[ autoscaling.StepAdjustments(MetricIntervalUpperBound=0, ScalingAdjustment=-1) ], ) self.ec2_high_cpu_usage_alarm = cloudwatch.Alarm( "EC2HighCPUUsageAlarm", ActionsEnabled=True, AlarmActions=[Ref(self.scale_up_policy)], ComparisonOperator='GreaterThanThreshold', Dimensions=[ cloudwatch.MetricDimension(Name='AutoScalingGroupName', Value=Ref(self.auto_scaling_group)) ], EvaluationPeriods=3, MetricName='CPUUtilization', Namespace='AWS/EC2', Period=300, Statistic='Average', Threshold='70', ) self.ec2_low_cpu_usage_alarm = cloudwatch.Alarm( "EC2LowCPUUsageAlarm", ActionsEnabled=True, AlarmActions=[Ref(self.scale_down_policy)], ComparisonOperator='LessThanThreshold', Dimensions=[ cloudwatch.MetricDimension(Name='AutoScalingGroupName', Value=Ref(self.auto_scaling_group)) ], EvaluationPeriods=3, MetricName='CPUUtilization', Namespace='AWS/EC2', Period=300, Statistic='Average', Threshold='20', )