def _add_autopush_iam_roles(self): firehose_extras = [] if self.use_firehose: # Add in the firehose permissions firehose_extras.append( Statement(Effect=Allow, Action=[ Action("firehose", "PutRecord"), Action("firehose", "PutRecordBatch"), ], Resource=[ GetAtt(self.FirehoseLogstream, "Arn"), ])) self.PushServerRole = self.add_resource( Role( "AutopushServerRole", AssumeRolePolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement(Effect=Allow, Action=[AssumeRole], Principal=Principal("Service", "ec2.amazonaws.com")) ]), Path="/", )) self.add_resource( PolicyType( "AutopushServerRolePolicy", PolicyName="AutopushServerRole", PolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement( Effect=Allow, Action=[ ddb.BatchGetItem, ddb.BatchWriteItem, ddb.GetItem, ddb.PutItem, ddb.DeleteItem, ddb.UpdateItem, ddb.Query, ddb.Scan, ], Resource=[ Join("", [ "arn:aws:dynamodb:us-east-1:*:table/", Ref(self.PushTablePrefix), "_*" ]) ]), Statement(Effect=Allow, Action=[ ddb.ListTables, ddb.DescribeTable, ddb.CreateTable, ], Resource=["*"]) ] + firehose_extras), Roles=[Ref(self.PushServerRole)]))
def _setup_firehose_custom_resource(self): # Setup the FirehoseLambda CloudFormation Custom Resource self.FirehoseLambdaCFExecRole = self.add_resource( Role( "FirehoseLambdaCFRole", AssumeRolePolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement(Effect=Allow, Action=[AssumeRole], Principal=Principal("Service", "lambda.amazonaws.com")) ]), Path="/", )) self.FirehoseLambdaPolicy = self.add_resource( PolicyType("FirehoseCFPolicy", PolicyName="FirehoseLambdaCFRole", PolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement(Effect=Allow, Action=[ Action("logs", "CreateLogGroup"), Action("logs", "CreateLogStream"), Action("logs", "PutLogEvents"), ], Resource=["arn:aws:logs:*:*:*"]), Statement(Effect=Allow, Action=[ Action("firehose", "CreateDeliveryStream"), Action("firehose", "DeleteDeliveryStream"), Action("firehose", "ListDeliveryStreams"), Action("firehose", "DescribeDeliveryStream"), Action("firehose", "UpdateDestination"), ], Resource=["*"]) ]), Roles=[Ref(self.FirehoseLambdaCFExecRole)], DependsOn="FirehoseLambdaCFRole")) self.FirehoseCFCustomResource = self.add_resource( Function( "FirehoseCustomResource", Description=( "Creates, updates, and deletes Firehose delivery streams"), Runtime="python2.7", Timeout=300, Handler="lambda_function.lambda_handler", Role=GetAtt(self.FirehoseLambdaCFExecRole, "Arn"), Code=Code( S3Bucket="cloudformation-custom-resources", S3Key="firehose_lambda.zip", ), DependsOn="FirehoseCFPolicy"))
def handle_cross_account_permissions( family: ComposeFamily, service: ComposeService, settings: ComposeXSettings, parameter_name: str, config_value: str, ): """ Function to automatically add cross-account role access for FireHose to the specified role ARN :param family: :param service: :param settings: :param parameter_name: :param config_value: :return: """ try: validate_iam_role_arn(config_value) except ValueError: LOG.error( f"{family.name}.{service.name} - FireLens config for firehose role_arn is invalid" ) raise policy_title = ( f"{family.logical_name}{service.logical_name}LoggingFirehoseCrossAccount" ) if policy_title in family.template.resources: policy = family.template.resources[policy_title] resource = policy.PolicyDocument["Statement"][0]["Resource"] if isinstance(resource, str): resource = [resource] if config_value not in resource: policy.PolicyDocument["Statement"][0]["Resource"].append( config_value) else: policy = PolicyType( policy_title, PolicyName=Sub( f"{family.logical_name}{service.logical_name}FireHoseCrossAccountAccess${{STACK_ID}}", STACK_ID=STACK_ID_SHORT, ), PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Sid": "LoggingFirehoseCrossAccount", "Effect": "Allow", "Action": ["sts:AssumeRole"], "Resource": [config_value], }], }, Roles=family.iam_manager.task_role.name, ) add_resource(family.template, policy) return config_value
def base_template(self): ret = super(MyConfigParser, self).base_template() salt_bucket = Bucket("SaltBucket", AccessControl="BucketOwnerFullControl", BucketName="{0}-salt".format(self.stack_name)) ret.add_resource(salt_bucket) arn = Join("", ["arn:aws:s3:::", Ref(salt_bucket), "/*"]) salt_bucket_policy = { 'Action': ['s3:Get*', 's3:List*'], "Resource": arn, 'Effect': 'Allow' } salt_role_policy = PolicyType( "S3SaltPolicy", PolicyName="S3SaltPolicy", PolicyDocument={"Statement": [salt_bucket_policy]}, Roles=[Ref("BaseHostRole")], ) ret.add_resource(salt_role_policy) arn = Join("", [ "arn:aws:kms:", Ref('AWS::Region'), ':', Ref('AWS::AccountId'), ':key/', self.kms_key_id ]) kms_policy = { "Sid": "AllowUseOfTheKey", "Effect": "Allow", "Action": ["kms:Decrypt", "kms:DescribeKey"], "Resource": arn } kms_role_policy = PolicyType( "KMSPolicy", PolicyName="KMSPolicy", PolicyDocument={"Statement": [kms_policy]}, Roles=[Ref("BaseHostRole")], ) ret.add_resource(kms_role_policy) return ret
def bucket_policy2(): return PolicyType( 'RolePolicies', PolicyName="S3Download", # PolicyDocument=awacs.aws.Policy( PolicyDocument={ Statement(Action=Action(s3="GetObject"), Effect="Allow", Resource="arn:aws:s3:::tesis.project.files/*") }, Roles=[Ref('InstanceRole')])
def _setup_s3writer_custom_resource(self): self.S3WriterLambdaCFExecRole = self.add_resource( Role( "S3WriterLambdaCFRole", AssumeRolePolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement(Effect=Allow, Action=[AssumeRole], Principal=Principal("Service", "lambda.amazonaws.com")) ]), Path="/", )) self.S3WriterCFPolicy = self.add_resource( PolicyType("S3WriterCFPolicy", PolicyName="S3WriterLambdaCFRole", PolicyDocument=Policy( Version="2012-10-17", Statement=[ Statement(Effect=Allow, Action=[ Action("logs", "CreateLogGroup"), Action("logs", "CreateLogStream"), Action("logs", "PutLogEvents"), ], Resource=["arn:aws:logs:*:*:*"]), Statement(Effect=Allow, Action=[ s3.DeleteObject, s3.ListBucket, s3.PutObject, s3.GetObject, ], Resource=["*"]) ]), Roles=[Ref(self.S3WriterLambdaCFExecRole)], DependsOn="S3WriterLambdaCFRole")) self.S3WriterCFCustomResource = self.add_resource( Function( "S3WriterCustomResource", Description=( "Creates, updates, and deletes S3 Files with custom content" ), Runtime="python2.7", Timeout=300, Handler="lambda_function.lambda_handler", Role=GetAtt(self.S3WriterLambdaCFExecRole, "Arn"), Code=Code( S3Bucket="cloudformation-custom-resources", S3Key="s3writer_lambda.zip", ), DependsOn="S3WriterCFPolicy"))
def bucket_policy(): return PolicyType( 'RolePolicies', PolicyName="S3Download", # PolicyDocument=awacs.aws.Policy( PolicyDocument={ "Statement": [{ "Action": ["s3:GetObject", "kms:decrypt"], "Effect": "Allow", "Resource": "arn:aws:s3:::tesis.project.files/*" }] }, Roles=[Ref('InstanceRole')])
def render(self, app_name=None, stage_name=None, username=None, function_bucket=None, static_bucket=None, aws_region_name='us-east-1'): self.app_name = app_name self.stage_name = stage_name self.username = username self.function_bucket = function_bucket self.static_bucket = static_bucket self.aws_region_name = aws_region_name self.t = Template() self.t.add_description( "Zappa Template for {app_name}-{stage_name} ".format( app_name=self.app_name, stage_name=self.stage_name)) zappa_user = self.t.add_resource(User(self.username)) zappa_user_keys = self.t.add_resource( AccessKey("ZappaUserKeys", Status="Active", UserName=Ref(zappa_user))) self.t.add_resource( PolicyType( alpha_num_pattern.sub( '', "{app_name}{stage_name}".format( app_name=self.app_name, stage_name=self.stage_name)), Users=[Ref(zappa_user)], PolicyName="zappa-{app_name}-{stage_name}".format( app_name=self.app_name, stage_name=self.stage_name), PolicyDocument=Policy( Version="2012-10-17", Statement=self.get_statement_list(), ), )) self.t.add_output( Output( "AccessKey", Value=Ref(zappa_user_keys), Description="AWSAccessKeyId of new user", )) self.t.add_output( Output( "SecretKey", Value=GetAtt(zappa_user_keys, "SecretAccessKey"), Description="AWSSecretKey of new user", )) return self.t.to_json()
def create_prod_template(jasontemplate): t = Template() eksrole = t.add_resource( Role("EKSRoletest", RoleName="EKS", ManagedPolicyArns=[ "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy", "arn:aws:iam::aws:policy/AmazonEKSServicePolicy" ], AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "sts:AssumeRole" }] }, Path="/")) t.add_resource( PolicyType("ekspolicy", PolicyName="eksypolicy", PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Sid": "1", "Effect": "Allow", "Action": [ "ec2:DescribeRegions", "ec2:DescribeImages", "ec2:DescribeInstances", "ec2:DescribeTags", "ec2:DescribeAvailabilityZones", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeVpcs", "iam:ListAccountAliases" ], "Resource": ["*"] }] }, Roles=[Ref(eksrole)])) role_id = GetAtt(eksrole, "Arn") return t, role_id
def set_repository_credentials(family, settings): """ Method to go over each service and identify which ones have credentials to pull the Docker image from a private repository :param ecs_composex.ecs.ecs_family.ComposeFamily family: :param ecs_composex.common.settings.ComposeXSettings settings: :return: """ for service in family.services: if not service.x_repo_credentials: continue if service.x_repo_credentials.startswith("arn:aws"): secret_arn = service.x_repo_credentials elif service.x_repo_credentials.startswith("secrets::"): secret_name = service.x_repo_credentials.split("::")[-1] secret_arn = identify_repo_credentials_secret(settings, family, secret_name) else: raise ValueError( "The secret for private repository must be either an ARN or the name of a secret defined in secrets" ) setattr( service.container_definition, "RepositoryCredentials", RepositoryCredentials(CredentialsParameter=secret_arn), ) policy = PolicyType( "AccessToRepoCredentialsSecret", PolicyName="AccessToRepoCredentialsSecret", PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["secretsmanager:GetSecretValue"], "Sid": "AccessToRepoCredentialsSecret", "Resource": [secret_arn], } ], }, Roles=[family.iam_manager.exec_role.name], ) if family.template and policy.title not in family.template.resources: family.template.add_resource(policy)
def grant_log_group_access(stream: DeliveryStream) -> PolicyType: policy = PolicyType( f"{stream.logical_name}ToCloudWatchLogs", PolicyName="CWAccess", PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Sid": "WriteToCloudWatchLogGroup", "Effect": "Allow", "Action": ["logs:CreateLogStream", "logs:PutLogEvents"], "Resource": GetAtt(stream.log_group, "Arn"), }], }, Roles=[Ref(stream.iam_manager.service_linked_role)], ) return policy
def identify_repo_credentials_secret(settings, task, secret_name): """ Function to identify the secret_arn :param settings: :param ComposeFamily task: :param secret_name: :return: """ for secret in settings.secrets: if secret.name == secret_name: secret_arn = secret.arn if secret_name not in [s.name for s in settings.secrets]: raise KeyError( f"secret {secret_name} was not found in the defined secrets", [s.name for s in settings.secrets], ) if ( secret.kms_key_arn and task.template and "RepositoryCredsKmsKeyAccess" not in task.template.resources ): task.template.add_resource( PolicyType( "RepositoryCredsKmsKeyAccess", PolicyName="RepositoryCredsKmsKeyAccess", PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["kms:Decrypt"], "Resource": [secret.kms_key_arn], } ], }, Roles=[task.exec_role.name], ) ) return secret_arn return None
def apply_ecs_execute_command_permissions(family, settings): """ Set the IAM Policies in place to allow ECS Execute SSM and Logging :param settings: :return: """ policy_title = "EnableEcsExecuteCommand" role_stack = family.iam_manager.task_role.stack task_role = Ref(family.iam_manager.task_role.cfn_resource) if policy_title not in role_stack.stack_template.resources: policy = role_stack.stack_template.add_resource( PolicyType( policy_title, PolicyName="EnableExecuteCommand", PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel", ], "Resource": "*", }], }, Roles=[task_role], )) set_ecs_cluster_logging_access(settings, policy, role_stack) else: expand_policy_roles(role_stack, policy_title, task_role) setattr( family.ecs_service.ecs_service, "EnableExecuteCommand", family.enable_execute_command, )
def add_task_iam_access_to_access_point(family, access_points, efs): """ Function to add IAM Permissions to mount to EFS via AccessPoint for ECS Task :param ecs_composex.ecs.ecs_family.ComposeFamily family: :param list<troposphere.efs.AccessPoint> access_points: :param ecs_composex.efs.efs_stack.Efs efs: """ policy = PolicyType( f"{family.logical_name}IamAccess", PolicyName=f"IamAccessToEfs{efs.logical_name}", PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Sid": f"{family.logical_name}EfsAccess", "Effect": "Allow", "Action": [ "elasticfilesystem:ClientMount", "elasticfilesystem:ClientWrite", "elasticfilesystem:ClientRootAccess", ], "Resource": [Ref(efs.attributes_outputs[FS_ARN]["ImportParameter"])], "Condition": { "StringEquals": { "elasticfilesystem:AccessPointArn": [ GetAtt(access_point, "Arn") for access_point in access_points ] } }, }], }, Roles=[family.iam_manager.task_role.name], ) family.template.add_resource(policy)
def create_iam_profile(self): t = self.template # Create EC2 Container Service Role t.add_resource( Role( "ecsServiceRole", AssumeRolePolicyDocument=get_ecs_assumerole_policy(), Path="/", Policies=[ Policy(PolicyName="ecsServiceRolePolicy", PolicyDocument=service_role_policy()) ])) # Role for Empire Controllers t.add_resource( Role( "EmpireControllerRole", AssumeRolePolicyDocument=get_default_assumerole_policy(), Path="/", Policies=[ Policy(PolicyName="EmpireControllerPolicy", PolicyDocument=empire_policy())])) # Add SNS Events policy if Events are enabled t.add_resource( PolicyType( "SNSEventsPolicy", PolicyName="EmpireSNSEventsPolicy", Condition="EnableSNSEvents", PolicyDocument=sns_events_policy(Ref("EventTopic")), Roles=[Ref("EmpireControllerRole")])) t.add_resource( InstanceProfile( "EmpireControllerProfile", Path="/", Roles=[Ref("EmpireControllerRole")])) t.add_output( Output("EmpireControllerRole", Value=Ref("EmpireControllerRole")))
def create_root_Policy(name, roles): """[ create policy resource TODO: should not use super root in production environment ] Arguments: name {[String]} -- [name of resource] roles {[String]} -- [Ref(role1), ...] Returns: [troposphere.resource] -- [ Policy resource ] """ return PolicyType(name, PolicyName=name + "RootPolicy", PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "*", "Resource": "*" }], }, Roles=roles)
def _instance_iam_role_policy(self): return PolicyType( "InstanceIamRolePolicy", PolicyName="AppInstanceIamRolePolicy", PolicyDocument=Policy(Statement=[ Statement(Effect=Allow, Action=[GetObject], Resource=[ "arn:aws:s3:::%s/*" % self.config['elb_logging_bucket'], "arn:aws:s3:::%s/*" % self.config['app_bucket'], "arn:aws:s3:::%s/*" % self.config['config_bucket'] ]), Statement(Effect=Allow, Action=[ListBucket], Resource=[ "arn:aws:s3:::%s" % self.config['elb_logging_bucket'], "arn:aws:s3:::%s" % self.config['app_bucket'], "arn:aws:s3:::%s" % self.config['config_bucket'] ]) ]), Roles=[Ref(self.instance_iam_role)])
}] }) Civ6Notif_RolePolicy = PolicyType("Civ6NotifRolePolicy", PolicyName="Civ6Notif_RolePolicy", PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*", "Effect": "Allow" }, { "Action": ["sns:Publish"], "Resource": "*", "Effect": "Allow" }, { "Action": ["lambda:*"], "Resource": "*", "Effect": "Allow" }] }, Roles=[Ref("Civ6NotifLambdaExecutionRole")]) Civ6Notif_SNS = Topic("Civ6NotifTopic", DisplayName="Civ6Notification")
k.update(kwargs) p = t.add_parameter(Parameter(name, **k)) param_refs[name] = Ref(p) return p param_refs = {} t = Template() t.add_description("Extra role policies for the Jenkins agent") param(str, "AgentStack") t.add_resource( PolicyType("Policy", PolicyName="ExtraPolicy", PolicyDocument={ "Statement": [{ "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::examplebucket", "Effect": "Allow" }] }, Roles=[ImportValue(Sub("${AgentStack}-AgentRole"))])) template = t.to_json(indent=2) if len(sys.argv) > 1: open(sys.argv[1], "w").write(template + "\n") else: print(template)
def generate_template(d): # Set template metadata t = Template() t.add_version("2010-09-09") t.set_description(d["cf_template_description"]) # aws_account_id = Ref("AWS::AccountId") # aws_region = Ref("AWS::Region") # ALB SG ALBSG = t.add_resource( SecurityGroup( "ALBSG", GroupDescription="Enable HTTP access.", SecurityGroupIngress=[ SecurityGroupRule(IpProtocol="tcp", FromPort="80", ToPort="80", CidrIp="0.0.0.0/0") ], VpcId=ImportValue(d["network_stack_name"] + "-VPCId"), )) # ALB ALB = t.add_resource( elb.LoadBalancer( "ALB", Name=d["project_name"], Scheme="internet-facing", SecurityGroups=[Ref("ALBSG")], Subnets=[ ImportValue(d["network_stack_name"] + "-PublicSubnetId1"), ImportValue(d["network_stack_name"] + "-PublicSubnetId2"), ], Tags=Tags(d["tags"]), )) # ECS cluster ECSCluster = t.add_resource( Cluster("ECSCluster", ClusterName=d["project_name"], Tags=Tags(d["tags"]))) # ECS cluster SG ClusterSG = t.add_resource( SecurityGroup( "ClusterSG", GroupDescription="Enable HTTP access.", SecurityGroupIngress=[ SecurityGroupRule( IpProtocol="tcp", FromPort="0", ToPort="65535", SourceSecurityGroupId=Ref(ALBSG), ) ], VpcId=ImportValue(d["network_stack_name"] + "-VPCId"), )) # ALB listener listener80 = t.add_resource( elb.Listener( "Listener80", Port="80", Protocol="HTTP", LoadBalancerArn=Ref("ALB"), DefaultActions=[ elb.Action( Type="fixed-response", FixedResponseConfig=elb.FixedResponseConfig( StatusCode="200", MessageBody=( "This is a fixed response for the default " "ALB action"), ContentType="text/plain", ), ) ], )) # ECS service role ECSClusterRole = t.add_resource( Role("ECSClusterRole", RoleName="ECSClusterRole", AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": "sts:AssumeRole", }], })) # ECS Cluster Role Policy t.add_resource( PolicyType( 'ECSClusterRolePolicy', PolicyName="ECSCLusterRolePolicy", Roles=[Ref(ECSClusterRole)], PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Sid": "ECSTaskManagement", "Effect": "Allow", "Action": [ "ec2:AttachNetworkInterface", "ec2:CreateNetworkInterface", "ec2:CreateNetworkInterfacePermission", "ec2:DeleteNetworkInterface", "ec2:DeleteNetworkInterfacePermission", "ec2:Describe*", "ec2:DetachNetworkInterface", "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:Describe*", "elasticloadbalancing:RegisterInstancesWithLoadBalancer", "elasticloadbalancing:RegisterTargets", "route53:ChangeResourceRecordSets", "route53:CreateHealthCheck", "route53:DeleteHealthCheck", "route53:Get*", "route53:List*", "route53:UpdateHealthCheck", "servicediscovery:DeregisterInstance", "servicediscovery:Get*", "servicediscovery:List*", "servicediscovery:RegisterInstance", "servicediscovery:UpdateInstanceCustomHealthStatus", "ecr:*", "cloudwatch:*", "logs:*", "iam:*", ], "Resource": "*" }, { "Sid": "AutoScaling", "Effect": "Allow", "Action": ["autoscaling:Describe*"], "Resource": "*" }, { "Sid": "AutoScalingManagement", "Effect": "Allow", "Action": [ "autoscaling:DeletePolicy", "autoscaling:PutScalingPolicy", "autoscaling:SetInstanceProtection", "autoscaling:UpdateAutoScalingGroup" ], "Resource": "*", "Condition": { "Null": { "autoscaling:ResourceTag/AmazonECSManaged": "false" } } }, { "Sid": "AutoScalingPlanManagement", "Effect": "Allow", "Action": [ "autoscaling-plans:CreateScalingPlan", "autoscaling-plans:DeleteScalingPlan", "autoscaling-plans:DescribeScalingPlans" ], "Resource": "*" }, { "Sid": "CWAlarmManagement", "Effect": "Allow", "Action": [ "cloudwatch:DeleteAlarms", "cloudwatch:DescribeAlarms", "cloudwatch:PutMetricAlarm" ], "Resource": "arn:aws:cloudwatch:*:*:alarm:*" }, { "Sid": "ECSTagging", "Effect": "Allow", "Action": ["ec2:CreateTags"], "Resource": "arn:aws:ec2:*:*:network-interface/*" }, { "Sid": "CWLogGroupManagement", "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:DescribeLogGroups", "logs:PutRetentionPolicy" ], "Resource": "arn:aws:logs:*:*:log-group:/aws/ecs/*" }, { "Sid": "CWLogStreamManagement", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:DescribeLogStreams", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:log-group:/aws/ecs/*:log-stream:*" }] })) # Codebuild role CodebuildDeveloperRole = t.add_resource( Role("CodebuildDeveloperRole", RoleName="CodebuilDevelopRole", AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": "sts:AssumeRole", }], })) # Codebuild developer role policy t.add_resource( PolicyType( 'CodebuildDeveloperRolePolicy', PolicyName="CodebuildDeveloperRolePolicy", Roles=[Ref(CodebuildDeveloperRole)], PolicyDocument={ "Statement": [{ "Action": [ "codebuild:StartBuild", "codebuild:StopBuild", "codebuild:BatchGet*", "codebuild:GetResourcePolicy", "codebuild:DescribeTestCases", "codebuild:List*", "codecommit:GetBranch", "codecommit:GetCommit", "codecommit:GetRepository", "codecommit:ListBranches", "cloudwatch:GetMetricStatistics", "events:DescribeRule", "events:ListTargetsByRule", "events:ListRuleNamesByTarget", "logs:GetLogEvents", "s3:*", "logs:*", "ecr:*" ], "Effect": "Allow", "Resource": "*" }, { "Effect": "Allow", "Action": ["ssm:PutParameter"], "Resource": "arn:aws:ssm:*:*:parameter/CodeBuild/*" }, { "Sid": "CodeStarNotificationsReadWriteAccess", "Effect": "Allow", "Action": [ "codestar-notifications:CreateNotificationRule", "codestar-notifications:DescribeNotificationRule", "codestar-notifications:UpdateNotificationRule", "codestar-notifications:Subscribe", "codestar-notifications:Unsubscribe" ], "Resource": "*", "Condition": { "StringLike": { "codestar-notifications:NotificationsForResource": "arn:aws:codebuild:*" } } }, { "Sid": "CodeStarNotificationsListAccess", "Effect": "Allow", "Action": [ "codestar-notifications:ListNotificationRules", "codestar-notifications:ListEventTypes", "codestar-notifications:ListTargets", "codestar-notifications:ListTagsforResource" ], "Resource": "*" }, { "Sid": "SNSTopicListAccess", "Effect": "Allow", "Action": ["sns:ListTopics", "sns:GetTopicAttributes"], "Resource": "*" }], "Version": "2012-10-17" })) # Codepipeline role CodePipelineRole = t.add_resource( Role("CodePipelineRole", RoleName="CodePipelineRole", AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "codepipeline.amazonaws.com" }, "Action": "sts:AssumeRole", }], })) t.add_resource( PolicyType( 'CodePipelineRolePolicy', PolicyName="CodePipelineRolePolicy", Roles=[Ref(CodePipelineRole)], PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Action": [ "cloudformation:CreateStack", "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:UpdateStack", "cloudformation:CreateChangeSet", "cloudformation:DeleteChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:SetStackPolicy", "cloudformation:ValidateTemplate", "iam:PassRole", "s3:*", ], "Resource": "*", "Effect": "Allow" }, { "Action": ["codebuild:BatchGetBuilds", "codebuild:StartBuild"], "Resource": "*", "Effect": "Allow" }, { "Action": ["ecr:*"], "Resource": "*", "Effect": "Allow" }, { "Action": [ "ecs:DescribeServices", "ecs:DescribeTaskDefinition", "ecs:DescribeTasks", "ecs:ListTasks", "ecs:RegisterTaskDefinition", "ecs:UpdateService" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "codedeploy:CreateDeployment", "codedeploy:GetDeployment", "codedeploy:GetApplication", "codedeploy:GetApplicationRevision", "codedeploy:RegisterApplicationRevision", "codedeploy:GetDeploymentConfig", "ecs:RegisterTaskDefinition", "iam:PassRole" ], "Resource": "*", "Effect": "Allow" }] })) # Outputs # ListenerArnHTTP t.add_output( Output( "ListenerArnHTTP", Description="Listener Arn (HTTP) of the newly created Listener", Export=Export(Sub("${AWS::StackName}-ListenerArnHTTP")), Value=Ref(listener80), )) t.add_output( Output( "ECSClusterRole", Description="ECS Cluster role with managed policy", Export=Export(Sub("${AWS::StackName}-ECSClusterRole")), Value=GetAtt(ECSClusterRole, "Arn"), )) t.add_output( Output( "CodePipelineRole", Description="CodePipeline role with managed policy", Export=Export(Sub("${AWS::StackName}-CodePipelineRole")), Value=GetAtt(CodePipelineRole, "Arn"), )) t.add_output( Output( "CodebuildDeveloperRole", Description="Codebuild role with managed policy", Export=Export(Sub("${AWS::StackName}-CodebuildDeveloperRole")), Value=GetAtt(CodebuildDeveloperRole, "Arn"), )) t.add_output( Output( "ECSClusterName", Description="ECS cluster name.", Export=Export(Sub("${AWS::StackName}-ECSClusterName")), # Value=GetAtt(ECSCluster, "Arn"), Value=Ref(ECSCluster), )) t.add_output( Output( "ALB", Description="ALB name.", Export=Export(Sub("${AWS::StackName}-ALBName")), Value=GetAtt(ALB, "LoadBalancerName"), )) t.add_output( Output( "ECSClusterSG", Description="ECS Cluster SG name.", Export=Export(Sub("${AWS::StackName}-ECSClusterSG")), Value=Ref(ClusterSG), )) return t
Handler=Ref(handler), MemorySize=Ref(memory_size), Role=GetAtt(function_role, "Arn"), Runtime="nodejs8.10", Timeout=Ref(timeout))) function_policy = t.add_resource( PolicyType("FunctionPolicy", PolicyDocument={ "Id": "FunctionPolicy", "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": ["arn:aws:logs:*:*:*"] }] }, PolicyName="function-policy", Roles=[Ref(function_role)])) alias = t.add_resource( Alias("LambdaAlias", Description="Cosmos Alias", FunctionName=Ref(aws_lambda), FunctionVersion="$LATEST", Name=Ref(env)))
"HyP3ScaleByBackloggedMessages", AutoScalingGroupName=Ref(processing_group), PolicyType="TargetTrackingScaling", TargetTrackingConfiguration=TargetTrackingConfiguration( CustomizedMetricSpecification=CustomizedMetricSpecification( MetricName=custom_metric_name, Namespace=Ref('AWS::StackName'), Statistic="Average"), DisableScaleIn=True, TargetValue=1.0 # Keep a ratio of 1 message per instance ))) terminate_instance = t.add_resource( PolicyType( "HyP3InstanceTerminateSelf", PolicyName="TerminateSelf", PolicyDocument=Policy(Statement=[ Statement(Effect=Allow, Action=[TerminateInstanceInAutoScalingGroup], Resource=[ Join(":", [ "arn", "aws", "autoscaling", Ref("AWS::Region"), Ref("AWS::AccountId"), "autoScalingGroup", "*", Sub("autoScalingGroupName/${GroupName}", GroupName=Ref(processing_group)) ]) ]) ]), Roles=[Ref(role)]))
def create_ecs_resources(self): t = self.template # Give the instances access that the Empire daemon needs. t.add_resource( PolicyType( "AccessPolicy", PolicyName="empire", PolicyDocument=empire_policy({ "Environment": Ref("Environment"), "CustomResourcesTopic": Ref("CustomResourcesTopic"), "CustomResourcesQueue": (GetAtt("CustomResourcesQueue", "Arn")), "TemplateBucket": (Join("", ["arn:aws:s3:::", Ref("TemplateBucket"), "/*"])) }), Roles=[Ref("InstanceRole")])) t.add_resource( sns.Topic( EVENTS_TOPIC, DisplayName="Empire events", Condition="CreateSNSTopic", )) t.add_output( Output("EventsSNSTopic", Value=Ref(EVENTS_TOPIC), Condition="CreateSNSTopic")) # Add SNS Events policy if Events are enabled t.add_resource( PolicyType("SNSEventsPolicy", PolicyName="EmpireSNSEventsPolicy", Condition="EnableSNSEvents", PolicyDocument=sns_events_policy( If("CreateSNSTopic", Ref(EVENTS_TOPIC), Ref("EventsSNSTopicName"))), Roles=[Ref("InstanceRole")])) # Add run logs policy if run logs are enabled t.add_resource( PolicyType("RunLogsPolicy", PolicyName="EmpireRunLogsPolicy", Condition="EnableCloudwatchLogs", PolicyDocument=runlogs_policy( If("CreateRunLogsGroup", Ref(RUN_LOGS), Ref("RunLogsCloudwatchGroup"))), Roles=[Ref("InstanceRole")])) # Allow the controller to write empire events to kinesis if kinesis is # enabled. t.add_resource( PolicyType("AppEventStreamPolicy", PolicyName="EmpireAppEventStreamPolicy", Condition="EnableAppEventStream", PolicyDocument=logstream_policy(), Roles=[Ref("InstanceRole")])) t.add_resource( ecs.TaskDefinition( "TaskDefinition", Volumes=[ ecs.Volume( Name="dockerSocket", Host=ecs.Host(SourcePath="/var/run/docker.sock")), ecs.Volume(Name="dockerCfg", Host=ecs.Host(SourcePath="/root/.dockercfg")) ], ContainerDefinitions=[ ecs.ContainerDefinition( Command=["server", "-automigrate=true"], Name="empire", Environment=self.get_empire_environment(), Essential=True, Image=Ref("DockerImage"), MountPoints=[ ecs.MountPoint( SourceVolume="dockerSocket", ContainerPath="/var/run/docker.sock", ReadOnly=False), ecs.MountPoint(SourceVolume="dockerCfg", ContainerPath="/root/.dockercfg", ReadOnly=False) ], PortMappings=[ ecs.PortMapping(HostPort=8081, ContainerPort=8081) ], Cpu=Ref("TaskCPU"), Memory=Ref("TaskMemory")) ])) t.add_resource( Role("ServiceRole", AssumeRolePolicyDocument=get_ecs_assumerole_policy(), Path="/", Policies=[ Policy(PolicyName="ecs-service-role", PolicyDocument=service_role_policy()) ])) t.add_resource( ecs.Service( "Service", Cluster=Ref("ControllerCluster"), DeploymentConfiguration=ecs.DeploymentConfiguration( MaximumPercent=Ref("ServiceMaximumPercent"), MinimumHealthyPercent=Ref("ServiceMinimumHealthyPercent"), ), DesiredCount=Ref("DesiredCount"), LoadBalancers=[ ecs.LoadBalancer(ContainerName="empire", ContainerPort=8081, LoadBalancerName=Ref("LoadBalancer")) ], Role=Ref("ServiceRole"), TaskDefinition=Ref("TaskDefinition")))
def add_service_roles(template): """ Function to create the IAM roles for the ECS task :param config: ecs_service configuration :type config: ecs_composex.ecs.ServiceConfig :param template: ecs_service template to add the resources to :type template: troposphere.Template """ execution_role = Role( EXEC_ROLE_T, template=template, AssumeRolePolicyDocument=service_role_trust_policy("ecs-tasks"), Description=Sub( f"Execution role for ${{{SERVICE_NAME_T}}} in ${{{CLUSTER_NAME_T}}}" ), ) PolicyType( f"{EXEC_ROLE_T}Policy", template=template, PolicyName=Sub(f"EcsExecRole"), PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowsForEcrPullFromEcsAgent", "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:DescribeRepositories", "ecr:ListImages", "ecr:DescribeImages", "ecr:BatchGetImage", ], "Resource": ["*"], }, { "Sid": "AllowEcsAgentOrientedTasks", "Effect": "Allow", "Action": ["ecs:DiscoverPollEndpoint", "ecs:Poll", "ecs:Submit*"], "Resource": ["*"], }, { "Sid": "AllowsEcsAgentToPerformActionsForMicroservice", "Effect": "Allow", "Action": [ "ec2:AttachNetworkInterface", "ec2:CreateNetworkInterface", "ec2:CreateNetworkInterfacePermission", "ec2:DeleteNetworkInterface", "ec2:DeleteNetworkInterfacePermission", "ec2:Describe*", "ec2:DetachNetworkInterface", "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:Describe*", "elasticloadbalancing:RegisterInstancesWithLoadBalancer", "elasticloadbalancing:RegisterTargets", ], "Resource": ["*"], }, ], }, Roles=[Ref(execution_role)], ) policies = [] managed_policies = [] Role( TASK_ROLE_T, template=template, AssumeRolePolicyDocument=service_role_trust_policy("ecs-tasks"), Description=Sub(f"TaskRole - ${{{SERVICE_NAME_T}}} in ${{{CLUSTER_NAME_T}}}"), ManagedPolicyArns=managed_policies, Policies=policies, )
} }] })) iam_policy_resource = t.add_resource( PolicyType("IAMPolicy", PolicyName="bootstrap", Roles=[Ref(iam_role_resource)], PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Action": ["ec2:DescribeTags", "ec2:CreateTags"], "Resource": ["*"], "Effect": "Allow" }, { "Action": [ "route53:ListHostedZones", "route53:ChangeResourceRecordSets" ], "Resource": ["*"], "Effect": "Allow" }] })) iam_instanceprofile_resource = t.add_resource( InstanceProfile("IAMInstanceProfile", Path="/", Roles=[Ref(iam_role_resource)]))
def create_template(): template = Template(Description="User-defined code") deployment_id = template.add_parameter( Parameter( "DeploymentId", Type="String", ) ) vpc_id = template.add_parameter( Parameter( "VpcId", Type="String", ) ) subnet_ids = template.add_parameter( Parameter( "SubnetIds", Type="CommaDelimitedList", ) ) file_system_access_point_arn = template.add_parameter( Parameter( "FileSystemAccessPointArn", Type="String", ) ) image_uri = template.add_parameter( Parameter( "ImageUri", Type="String", ) ) security_group = template.add_resource( SecurityGroup( "SecurityGroup", GroupDescription=StackName, VpcId=Ref(vpc_id), ) ) role = template.add_resource( Role( "Role", AssumeRolePolicyDocument=PolicyDocument( Version="2012-10-17", Statement=[ Statement( Effect=Allow, Action=[sts.AssumeRole], Principal=Principal("Service", "lambda.amazonaws.com"), ), ], ), Policies=[ Policy( PolicyName="vpc-access", PolicyDocument=PolicyDocument( Version="2012-10-17", Statement=[ Statement( Effect=Allow, Action=[ ec2.CreateNetworkInterface, ec2.DescribeNetworkInterfaces, ec2.DeleteNetworkInterface, ec2.AssignPrivateIpAddresses, ec2.UnassignPrivateIpAddresses, ], Resource=["*"], ), ], ), ), ], ) ) function, alias = common.add_versioned_lambda( template, Ref(deployment_id), Function( "Function", MemorySize=256, Role=GetAtt(role, "Arn"), VpcConfig=VPCConfig( SecurityGroupIds=[Ref(security_group)], SubnetIds=Ref(subnet_ids), ), FileSystemConfigs=[ FileSystemConfig( Arn=Ref(file_system_access_point_arn), LocalMountPath="/mnt/storage", ), ], PackageType="Image", Code=Code( ImageUri=Ref(image_uri), ), ImageConfig=ImageConfig( Command=[ Join(":", (handler.__module__, handler.__name__)), ], ), ), ) log_group = template.add_resource( LogGroup( "LogGroup", LogGroupName=Join("/", ["/aws/lambda", Ref(function)]), RetentionInDays=7, ) ) policy = template.add_resource( PolicyType( "Policy", PolicyName=Ref(function), PolicyDocument=PolicyDocument( Version="2012-10-17", Statement=[ Statement( Effect=Allow, Resource=GetAtt(log_group, "Arn"), Action=[logs.CreateLogStream, logs.PutLogEvents], ), ], ), Roles=[Ref(role)], ) ) template.add_output( Output( "FunctionAliasArn", Value=Ref(alias), ) ) return template
PolicyType( "IAMPolicies", PolicyName=Ref(RoleParam), Groups=[Ref(GroupParam)], PolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "ec2:*", "s3:*", "rds:*", "elasticsearch:*", "sqs:*", "elasticache:*", "events:DescribeRule", "events:ListRuleNamesByTarget", "events:ListRules", "events:ListTargetsByRule", "events:TestEventPattern", "events:DescribeEventBus", "kms:ListAliases", "kms:DescribeKey", "application-autoscaling:DescribeScalableTargets", "application-autoscaling:DescribeScalingActivities", "application-autoscaling:DescribeScalingPolicies", "cloudwatch:DescribeAlarmHistory", "cloudwatch:DescribeAlarms", "cloudwatch:DescribeAlarmsForMetric", "cloudwatch:GetMetricStatistics", "cloudwatch:ListMetrics", "datapipeline:DescribeObjects", "datapipeline:DescribePipelines", "datapipeline:GetPipelineDefinition", "datapipeline:ListPipelines", "datapipeline:QueryObjects", "dynamodb:BatchGetItem", "dynamodb:Describe*", "dynamodb:List*", "dynamodb:GetItem", "dynamodb:Query", "dynamodb:Scan", "dax:Describe*", "dax:List*", "dax:GetItem", "dax:BatchGetItem", "dax:Query", "dax:Scan", "iam:GetRole", "iam:ListRoles", "sns:ListSubscriptionsByTopic", "sns:ListTopics", "lambda:ListFunctions", "lambda:ListEventSourceMappings", "lambda:GetFunctionConfiguration", "resource-groups:ListGroups", "resource-groups:ListGroupResources", "resource-groups:GetGroup", "resource-groups:GetGroupQuery", "tag:GetResources" ], "Resource": "*", "Condition": { "StringEquals": { "aws:RequestedRegion": Ref(RegionParam) } } }], }, DependsOn=IAMGroup))
def define_iam_permissions( resource_mapping_key, dest_resource, dest_resource_template, policy_title, access_type_policy_model, access_definition: Union[str, dict], resource_arns, access_subkey: str = None, roles=None, sid_override: str = None, ) -> None: """ If a policy already exists to manage resources of the same AWS Service, imports the policy, else, creates one. The SID of the policy allows grouping resources that have a similar access pattern together in the same statement policy, reducing the policy length (later, might allow for managed policies). If there were no SID set already in a statement, adds it. :param resource_mapping_key: :param dest_resource: :param troposphere.Template dest_resource_template: :param str policy_title: :param dict access_type_policy_model: :param str, dict access_definition: :param list resource_arns: :param str access_subkey: :param list roles: List of Role pointers to use as Policy targets """ new_policy_statement = copy.deepcopy(access_type_policy_model) sid_name = ( set_sid_name(access_definition, access_subkey) if not sid_override else sid_override ) if ( resource_mapping_key not in dest_resource.iam_manager.iam_modules_policies.keys() ): dest_resource.iam_manager.iam_modules_policies[ resource_mapping_key ] = PolicyType( policy_title, PolicyName=policy_title, PolicyDocument={"Version": "2012-10-17", "Statement": []}, Roles=roles, ) res_policy = dest_resource_template.add_resource( dest_resource.iam_manager.iam_modules_policies[resource_mapping_key] ) else: res_policy = dest_resource.iam_manager.iam_modules_policies[ resource_mapping_key ] policy_doc = getattr(res_policy, "PolicyDocument") policy_doc_statement = policy_doc["Statement"] for statement in policy_doc_statement: if keyisset("Sid", statement) and statement["Sid"] == sid_name: if not isinstance(statement["Resource"], list): statement["Resource"] = [statement["Resource"]] add_new_arns_to_statement_resource(statement["Resource"], resource_arns) break else: new_policy_statement["Sid"] = sid_name new_policy_statement["Resource"] = ( resource_arns if isinstance(resource_arns, list) else [resource_arns] ) policy_doc_statement.append(new_policy_statement)
def define_service_targets(stack, rule, cluster_arn): """ Function to define the targets for service. :param ecs_composex.events.events_stack.XStack stack: :param ecs_composex.events.events_stack.Rule rule: :param troposphere.Sub cluster_arn: :return: """ for service in rule.families_targets: service_sg_param = Parameter(f"{service[0].logical_name}GroupId", Type=SG_ID_TYPE) service_task_def_param = Parameter( f"{service[0].logical_name}{TASK_T}", Type="String") service_subnets_param = Parameter( f"{service[0].logical_name}{APP_SUBNETS.title}", Type=SUBNETS_TYPE) events_policy_doc = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ecs:RunTask"], "Resource": [Ref(service_task_def_param)], "Condition": { "ArnLike": { "ecs:cluster": cluster_arn } }, }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": ["*"], "Condition": { "StringLike": { "iam:PassedToService": Sub(f"ecs-tasks.${{{AWS_URL_SUFFIX}}}") } }, }, ], } task_events_policy_doc = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ecs:RunTask"], "Resource": [Ref(service[0].template.resources[TASK_T])], "Condition": { "ArnLike": { "ecs:cluster": cluster_arn } }, }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": ["*"], "Condition": { "StringLike": { "iam:PassedToService": Sub(f"ecs-tasks.${{{AWS_URL_SUFFIX}}}") } }, }, ], } events_policy = Policy(PolicyName="EventsAccess", PolicyDocument=events_policy_doc) if "EventsAccessPolicy" not in service[0].template.resources: service[0].template.add_resource( PolicyType( "EventsAccessPolicy", PolicyName="EventsAccess", PolicyDocument=task_events_policy_doc, Roles=[ service[0].iam_manager.task_role.name, service[0].iam_manager.exec_role.name, ], )) role_name = f"{rule.logical_name}IamRoleToTrigger{service[0].logical_name}" if role_name not in stack.stack_template.resources: role = stack.stack_template.add_resource( Role( f"{rule.logical_name}IamRoleToTrigger{service[0].logical_name}", AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [{ "Sid": "TrustPolicy", "Effect": "Allow", "Principal": { "Service": Sub(f"events.${{{AWS_URL_SUFFIX}}}") }, "Action": "sts:AssumeRole", }], }, ManagedPolicyArns=[], Policies=[events_policy], PermissionsBoundary=Ref(AWS_NO_VALUE), )) if service[0].iam_manager.permissions_boundary: role.PermissionsBoundary = service[ 0].iam_manager.permissions_boundary else: role = stack.stack_template.resources[role_name] add_parameters( stack.stack_template, [service_sg_param, service_task_def_param, service_subnets_param], ) stack.Parameters.update({ service_sg_param.title: GetAtt( service[0].logical_name, f"Outputs.{service[0].logical_name}GroupId", ), service_task_def_param.title: GetAtt( service[0].logical_name, f"Outputs.{service[0].task_definition.title}", ), service_subnets_param.title: GetAtt( service[0].logical_name, f"Outputs.{SERVICE_SUBNETS.title}", ), }) target = Target( EcsParameters=EcsParameters( NetworkConfiguration=NetworkConfiguration( AwsVpcConfiguration=AwsVpcConfiguration( Subnets=Ref(service_subnets_param), SecurityGroups=[Ref(service_sg_param)], AssignPublicIp=service[0].service_networking. eip_assign, )), PlatformVersion=Ref(FARGATE_VERSION), TaskCount=service[3], TaskDefinitionArn=Ref(service_task_def_param), LaunchType="FARGATE", ), Arn=cluster_arn, Id=service[0].logical_name, RoleArn=GetAtt(role, "Arn"), ) rule.cfn_resource.Targets.append(target) if service[0].logical_name not in stack.DependsOn: stack.DependsOn.append(service[0].logical_name) if (keyisset("DeleteDefaultService", service[4]) and SERVICE_T in service[0].template.resources): LOG.info( f"Deleting ECS Service definition from stack for {service[0].name}" ) del service[0].template.resources[SERVICE_T] if SERVICE_SCALING_TARGET in service[0].template.resources: LOG.warning( f"Target for event {rule.logical_name} also had scaling rules. Deleting" ) delete_service_from_template(service)
PolicyEcr = t.add_resource( PolicyType( 'PolicyEcr', PolicyName='EcrPolicy', PolicyDocument={ 'Version': '2012-10-17', 'Statement': [ { 'Action': ['ecr:GetAuthorizationToken'], 'Resource': ['*'], 'Effect': 'Allow' }, { 'Action': [ 'ecr:GetDownloadUrlForLayer', 'ecr:BatchGetImage', 'ecr:BatchCheckLayerAvailability' ], 'Resource': ['*'], 'Effect': 'Allow', 'Sid': 'AllowPull' }, ] }, Roles=[Ref('EcsClusterRole')], )) PolicyEcs = t.add_resource(