Exemplo n.º 1
0
    def _add_service(self, service_name, config):
        env_config = build_config(
            self.env,
            self.application_name,
            self.env_sample_file_path
        )
        container_definition_arguments = {
            "Environment": [
                Environment(Name=k, Value=v) for (k, v) in env_config
            ],
            "Name": service_name + "Container",
            "Image": self.ecr_image_uri + ':' + self.current_version,
            "Essential": 'true',
            "LogConfiguration": self._gen_log_config(service_name),
            "MemoryReservation": int(config['memory_reservation']),
            "Cpu": 0
        }

        if 'http_interface' in config:
            container_definition_arguments['PortMappings'] = [
                PortMapping(
                    ContainerPort=int(
                        config['http_interface']['container_port']
                    )
                )
            ]

        if config['command'] is not None:
            container_definition_arguments['Command'] = [config['command']]

        cd = ContainerDefinition(**container_definition_arguments)

        task_role = self.template.add_resource(Role(
            service_name + "Role",
            AssumeRolePolicyDocument=PolicyDocument(
                Statement=[
                    Statement(
                        Effect=Allow,
                        Action=[AssumeRole],
                        Principal=Principal("Service", ["ecs-tasks.amazonaws.com"])
                    )
                ]
            )
        ))

        td = TaskDefinition(
            service_name + "TaskDefinition",
            Family=service_name + "Family",
            ContainerDefinitions=[cd],
            TaskRoleArn=Ref(task_role)
        )
        self.template.add_resource(td)
        desired_count = self._get_desired_task_count_for_service(service_name)
        deployment_configuration = DeploymentConfiguration(
            MinimumHealthyPercent=100,
            MaximumPercent=200
        )
        if 'http_interface' in config:
            alb, lb, service_listener = self._add_alb(cd, service_name, config)
            svc = Service(
                service_name,
                LoadBalancers=[lb],
                Cluster=self.cluster_name,
                Role=Ref(self.ecs_service_role),
                TaskDefinition=Ref(td),
                DesiredCount=desired_count,
                DependsOn=service_listener.title,
                PlacementStrategies=self.PLACEMENT_STRATEGIES
            )
            self.template.add_output(
                Output(
                    service_name + 'EcsServiceName',
                    Description='The ECS name which needs to be entered',
                    Value=GetAtt(svc, 'Name')
                )
            )
            self.template.add_output(
                Output(
                    service_name + "URL",
                    Description="The URL at which the service is accessible",
                    Value=Sub("https://${" + alb.name + ".DNSName}")
                )
            )
            self.template.add_resource(svc)
        else:
            svc = Service(
                service_name,
                Cluster=self.cluster_name,
                TaskDefinition=Ref(td),
                DesiredCount=desired_count,
                DeploymentConfiguration=deployment_configuration,
                PlacementStrategies=self.PLACEMENT_STRATEGIES
            )
            self.template.add_output(
                Output(
                    service_name + 'EcsServiceName',
                    Description='The ECS name which needs to be entered',
                    Value=GetAtt(svc, 'Name')
                )
            )
            self.template.add_resource(svc)
        self._add_service_alarms(svc)
Exemplo n.º 2
0
Arquivo: ecr.py Projeto: zeus911/awacs
# Example taken from AWS docs:
# http://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html

from awacs.aws import Allow
from awacs.aws import Policy, Statement
import awacs.ecr as ecr

# AmazonEC2ContainerRegistryReadOnly
pd = Policy(Statement=[
    Statement(Effect=Allow,
              Action=[
                  ecr.GetAuthorizationToken,
                  ecr.BatchCheckLayerAvailability,
                  ecr.GetDownloadUrlForLayer,
                  ecr.GetRepositoryPolicy,
                  ecr.DescribeRepositories,
                  ecr.ListImages,
                  ecr.BatchGetImage,
              ],
              Resource=['*'])
])

print(pd.to_json())
Exemplo n.º 3
0
                FromPort='443',
                ToPort='443',
                CidrIp=quad_zero_ip),
            SecurityGroupRule(  # Web Interface Kibana
                IpProtocol='tcp',
                FromPort='5601',
                ToPort='5601',
                CidrIp=quad_zero_ip)
        ]))

jenkinsRole = t.add_resource(
    Role(
        "jenkinsRole",
        AssumeRolePolicyDocument=Policy(Statement=[
            Statement(Effect=Allow,
                      Action=[AssumeRole],
                      Principal=Principal("Service", ["ec2.amazonaws.com"]))
        ]),
        Path="/",
        Policies=[
            iam.Policy(
                PolicyName="JenkinsPolicies",
                PolicyDocument=Policy(Statement=[
                    Statement(
                        Effect=Allow,
                        Action=[
                            CancelUpdateStack, CreateStack, ListStackResources,
                            DescribeStackEvents, UpdateStack
                        ],
                        Resource=[Ref('AWS::StackId')],
                    ),
Exemplo n.º 4
0
def codebuild_policy_document(input_kwargs, build_data):

    user = "******"
    account = build_data["account_id"]

    pd = PolicyDocument(
        Version="2012-10-17",
        Id="Codebuild-Permissions",
        Statement=[
            Statement(
                Effect=Allow,
                Principal=Principal("AWS", [IAM_ARN(user, '', account)]),
                Action=[
                    codebuild.BatchDeleteBuilds, codebuild.BatchGetBuilds,
                    codebuild.BatchGetProjects, codebuild.BatchGetReportGroups,
                    codebuild.BatchGetReports, codebuild.BatchPutTestCases,
                    codebuild.CreateProject, codebuild.CreateReport,
                    codebuild.CreateReportGroup, codebuild.CreateWebhook,
                    codebuild.DeleteOAuthToken, codebuild.DeleteProject,
                    codebuild.DeleteReport, codebuild.DeleteReportGroup,
                    codebuild.DeleteResourcePolicy,
                    codebuild.DeleteSourceCredentials, codebuild.DeleteWebhook,
                    codebuild.DescribeTestCases, codebuild.GetResourcePolicy,
                    codebuild.ImportSourceCredentials,
                    codebuild.InvalidateProjectCache, codebuild.ListBuilds,
                    codebuild.ListBuildsForProject,
                    codebuild.ListConnectedOAuthAccounts,
                    codebuild.ListCuratedEnvironmentImages,
                    codebuild.ListProjects, codebuild.ListReportGroups,
                    codebuild.ListReports, codebuild.ListReportsForReportGroup,
                    codebuild.ListRepositories, codebuild.ListSharedProjects,
                    codebuild.ListSharedReportGroups,
                    codebuild.ListSourceCredentials,
                    codebuild.PersistOAuthToken, codebuild.PutResourcePolicy,
                    codebuild.StartBuild, codebuild.StopBuild,
                    codebuild.UpdateProject, codebuild.UpdateReport,
                    codebuild.UpdateReportGroup, codebuild.UpdateWebhook,
                    iam.PassRole, codecommit.GitPull
                ],
                Resource=['*']),
            Statement(Effect=Allow,
                      Principal=Principal("AWS", [IAM_ARN(user, '', account)]),
                      Action=[
                          logs.FilterLogEventlogs, logs.GetLogEvents,
                          logs.CreateLogGroup, logs.CreateLogStream,
                          logs.PutLogEvents
                      ],
                      Resource=['*']),
            Statement(Effect=Allow,
                      Principal=Principal("AWS", [IAM_ARN(user, '', account)]),
                      Action=[
                          s3.CreateBucket, s3.ListAccessPoints,
                          s3.ListAllMyBuckets, s3.ListBucket,
                          s3.ListBucketByTags, s3.ListBucketMultipartUploads,
                          s3.ListBucketVersions, s3.ListJobs,
                          s3.ListMultipartUploadParts, s3.ListObjects,
                          s3.PutObject, s3.GetObject, s3.GetBucketAcl,
                          s3.GetBucketLocation, s3.GetObjectVersion
                      ],
                      Resource=['*']),
            Statement(Effect=Allow,
                      Principal=Principal("AWS", [IAM_ARN(user, '', account)]),
                      Action=[
                          ecr.BatchCheckLayerAvailability,
                          ecr.GetDownloadUrlForLayer, ecr.BatchGetImage,
                          ecr.PutImage, ecr.InitiateLayerUpload,
                          ecr.UploadLayerPart, ecr.CompleteLayerUpload,
                          ecr.GetAuthorizationToken
                      ],
                      Resource=['*']),
            Statement(Effect=Allow,
                      Principal=Principal("AWS", [IAM_ARN(user, '', account)]),
                      Action=[ec2.DescribeSecurityGroups, ec2.DescribeSubnets],
                      Resource=['*']),
            Statement(Effect=Allow,
                      Principal=Principal("AWS", [IAM_ARN(user, '', account)]),
                      Action=[
                          ecs.RegisterTaskDefinition,
                          ecs.DescribeTaskDefinition, ecs.DescribeServices,
                          ecs.CreateService, ecs.ListServices,
                          ecs.UpdateService
                      ],
                      Resource=['*']),
        ])

    input_kwargs["policy"] = pd.to_json()

    return input_kwargs
Exemplo n.º 5
0
                                  CidrIp="0.0.0.0/0")
        ]))

ud = Base64(
    Join('\n', [
        "#!/bin/bash", "sudo yum install --enablerepo=epel -y git",
        "sudo yum install --enablerepo=epel -y ansible", AnsiblePullCmd,
        "echo '*/10 * * * * {}' > /etc/cron.d/ansible-pull".format(
            AnsiblePullCmd)
    ]))

t.add_resource(
    Role("Role",
         AssumeRolePolicyDocument=Policy(Statement=[
             Statement(Effect=Allow,
                       Action=[AssumeRole],
                       Principal=Principal("Service", ["ec2.amazonaws.com"]))
         ])))

t.add_resource(
    InstanceProfile("InstanceProfile", Path="/", Roles=[Ref("Role")]))

t.add_resource(
    IAMPolicy(
        "Policy",
        PolicyName="AllowS3",
        PolicyDocument=Policy(Statement=[
            Statement(Effect=Allow, Action=[Action("s3", "*")], Resource=["*"])
        ])))

t.add_resource(
Exemplo n.º 6
0
# put it in just one.
efs_mount_target = MountTarget("MyEFSMountTarget",
                               FileSystemId=Ref(efs_file_system),
                               SecurityGroups=[Ref(efs_security_group)],
                               SubnetId=Ref(subnetid_param))
template.add_resource(efs_mount_target)

# Create the policy that allows the instance to describe file systems and tags,
# so it can lookup the file system using AWS tags. An alternative would be to
# pass in the FileSystem name as UserData.
efs_host_role = Role(
    "EFSHostRole",
    AssumeRolePolicyDocument=Policy(Statement=[
        Statement(Effect=Allow,
                  Action=[
                      Action('elasticfilesystem', 'DescribeFileSystems'),
                      Action('elasticfilesystem', 'DescribeTags')
                  ],
                  Resource=["*"])
    ]))
template.add_resource(efs_host_role)

efs_host_instance_profile = InstanceProfile("EFSInstanceProfile",
                                            Roles=[Ref(efs_host_role)])
template.add_resource(efs_host_instance_profile)

# And finally the EC2 instance.
ec2_instance = Instance("Ec2Instance",
                        ImageId=FindInMap("RegionMap", Ref("AWS::Region"),
                                          "AMI"),
                        InstanceType="t1.micro",
                        KeyName=Ref(keyname_param),
Exemplo n.º 7
0
from troposphere.iam import Policy as IAMPolicy
from troposphere.s3 import Bucket, VersioningConfiguration

t = Template()
t.set_description("myeongjae.kim: myeongjae.kim Pipeline")

t.add_resource(
    Bucket("S3Bucket",
           VersioningConfiguration=VersioningConfiguration(
               Status="Enabled", )))

t.add_resource(
    Role("PipelineRole",
         AssumeRolePolicyDocument=Policy(Statement=[
             Statement(Effect=Allow,
                       Action=[AssumeRole],
                       Principal=Principal("Service",
                                           ["codepipeline.amazonaws.com"]))
         ]),
         Path="/",
         Policies=[
             IAMPolicy(PolicyName="MyeongjaeKimCodePipeline",
                       PolicyDocument={
                           "Statement": [
                               {
                                   "Effect": "Allow",
                                   "Action": "cloudformation:*",
                                   "Resource": "*"
                               },
                               {
                                   "Effect": "Allow",
                                   "Action": "codebuild:*",
Exemplo n.º 8
0
            'EC2Principal': 'ec2.amazonaws.com',
            'OpsWorksPrincipal': 'opsworks.amazonaws.com'
        },
        'us-west-2': {
            'EC2Principal': 'ec2.amazonaws.com',
            'OpsWorksPrincipal': 'opsworks.amazonaws.com'
        }
    })

web_server_role = Role(
    "WebServerRole",
    template=template,
    AssumeRolePolicyDocument=Policy(Statement=[
        Statement(Effect=Allow,
                  Action=[AssumeRole],
                  Principal=Principal("Service", [
                      FindInMap("Region2Principal", Ref("AWS::Region"),
                                "EC2Principal")
                  ]))
    ]),
    Path="/",
    Policies=[
        assets_management_policy,
        logging_policy,
        iam.Policy(
            PolicyName="EBBucketAccess",
            PolicyDocument=dict(Statement=[
                dict(
                    Effect="Allow",
                    Action=[
                        "s3:Get*",
                        "s3:List*",
Exemplo n.º 9
0
def CF_config(args):
    t = Template()

    t.add_description(
        "This AWS Cloudformation Template creates a stack necessary to run the SABER airflow pipeline."
    )

    #Set up iamRole
    iamRole = t.add_resource(
        Role("ecsTaskWithS3",
             AssumeRolePolicyDocument=Policy(
                 Version="2012-10-17",
                 Statement=[
                     Statement(Effect=Allow,
                               Action=[AssumeRole],
                               Principal=Principal(
                                   "Service", ["ecs-tasks.amazonaws.com"]))
                 ])))

    Vpc = t.add_parameter(
        Parameter(
            'VpcId',
            ConstraintDescription=
            'Must be a valid VPC ID. (Can be found here: https://console.aws.amazon.com/vpc/home?region=us-east-1#vpcs:sort=VpcId)',
            Type='String'))

    PrivateSubnetA = t.add_parameter(
        Parameter(
            'SubnetId',
            ConstraintDescription=
            "Must be a valid subnet Id wihthin same VPC id. (Can be found here: https://console.aws.amazon.com/vpc/home?region=us-east-1#subnets:search=vpc-6443921c;sort=State)",
            Type='String'))

    keyname_param = t.add_parameter(
        Parameter("KeyName",
                  Description="Key pair name for EC2 managment",
                  Type="String"))

    sec_group = t.add_parameter(
        Parameter("SecurityGroup",
                  Description="Security Group to access Ec2 instances",
                  Type="String"))

    BatchServiceRole = t.add_resource(
        Role(
            'BatchServiceRole',
            Path='/',
            Policies=[],
            ManagedPolicyArns=[
                'arn:aws:iam::aws:policy/AmazonS3FullAccess',
                'arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole',
            ],
            AssumeRolePolicyDocument={
                'Statement': [{
                    'Action': ['sts:AssumeRole'],
                    'Effect': 'Allow',
                    'Principal': {
                        'Service': ['batch.amazonaws.com']
                    }
                }]
            },
        ))

    BatchInstanceRole = t.add_resource(
        Role(
            'BatchInstanceRole',
            Path='/',
            Policies=[],
            ManagedPolicyArns=[
                'arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role'
            ],
            AssumeRolePolicyDocument={
                'Statement': [{
                    'Action': ['sts:AssumeRole'],
                    'Effect': 'Allow',
                    'Principal': {
                        'Service': ['ec2.amazonaws.com']
                    }
                }]
            },
        ))

    BatchInstanceProfile = t.add_resource(
        InstanceProfile(
            'BatchInstanceProfile',
            Path="/",
            Roles=[Ref(BatchInstanceRole)],
        ))

    BatchSecurityGroup = t.add_resource(
        SecurityGroup(
            'BatchSecurityGroup',
            VpcId=Ref(Vpc),  #Default Vpc
            GroupDescription='Enable access to Batch instances',
            Tags=Tags(Name='batch-sg'),
            SecurityGroupIngress=[
                # SecurityGroupRule(
                #     IpProtocol="tcp",
                #     FromPort="22",
                #     ToPort="22",
                #     CidrIp=Ref(sshlocation_param),
                # ),
            ]))

    BatchComputeEnvironment = t.add_resource(
        ComputeEnvironment(
            'GeneralComputeEnvironment',
            Type='MANAGED',
            State='ENABLED',
            ServiceRole=Ref(BatchServiceRole),
            ComputeResources=ComputeResources(
                'GeneralComputeResources',
                Type='EC2',
                DesiredvCpus=0,
                MinvCpus=0,
                MaxvCpus=256,
                InstanceTypes=['optimal'],
                InstanceRole=Ref(BatchInstanceProfile),
                SecurityGroupIds=[
                    GetAtt(BatchSecurityGroup, 'GroupId'),
                    Ref(sec_group)
                ],
                Subnets=[Ref(PrivateSubnetA)],
                Ec2KeyPair=Ref(keyname_param)),
            ComputeEnvironmentName="saber-batch-compute-environment"))

    GPUBatchComputeEnvironment = t.add_resource(
        ComputeEnvironment(
            'GPUComputeEnvironment',
            Type='MANAGED',
            State='ENABLED',
            ServiceRole=Ref(BatchServiceRole),
            ComputeResources=ComputeResources(
                'GPUComputeResources',
                Type='EC2',
                DesiredvCpus=0,
                MinvCpus=0,
                MaxvCpus=512,
                ImageId="ami-0612e39997371a677",
                InstanceTypes=['p2.xlarge'],
                InstanceRole=Ref(BatchInstanceProfile),
                SecurityGroupIds=[
                    GetAtt(BatchSecurityGroup, 'GroupId'),
                    Ref(sec_group)
                ],
                Subnets=[Ref(PrivateSubnetA)],
                Ec2KeyPair=Ref(keyname_param)),
            ComputeEnvironmentName="saber-batch-compute-environment-GPU-enabled"
        ))

    GPUJobQueue = t.add_resource(
        JobQueue('GPUJobQueue',
                 ComputeEnvironmentOrder=[
                     ComputeEnvironmentOrder(
                         ComputeEnvironment=Ref(GPUBatchComputeEnvironment),
                         Order=1),
                 ],
                 Priority=1,
                 State='ENABLED',
                 JobQueueName=args.job_queue_gpu))

    GenJobQueue = t.add_resource(
        JobQueue('GenJobQueue',
                 ComputeEnvironmentOrder=[
                     ComputeEnvironmentOrder(
                         ComputeEnvironment=Ref(BatchComputeEnvironment),
                         Order=1),
                 ],
                 Priority=1,
                 State='ENABLED',
                 JobQueueName=args.job_queue_gen))

    t.add_output([
        Output('BatchComputeEnvironment', Value=Ref(BatchComputeEnvironment)),
        Output('BatchSecurityGroup', Value=Ref(BatchSecurityGroup)),
        Output('ExampleJobQueue', Value=Ref(GenJobQueue)),
        Output('GPUComputeEnvironment', Value=Ref(BatchComputeEnvironment)),
        Output('ExampleJobQueueGPU', Value=Ref(GPUJobQueue))
    ])

    # Finally, write the template to a file
    template_fp = os.path.dirname(sys.argv[0])
    with open(template_fp + '/' + args.template_file, 'w') as f:
        f.write(t.to_json())
Exemplo n.º 10
0
    def __init__(self, paco_ctx, account_ctx, aws_region, stack_group,
                 stack_tags, env_ctx, app_id, grp_id, cdapp, role):
        super().__init__(paco_ctx,
                         account_ctx,
                         aws_region,
                         enabled=cdapp.is_enabled(),
                         config_ref=cdapp.paco_ref_parts,
                         iam_capabilities=["CAPABILITY_NAMED_IAM"],
                         stack_group=stack_group,
                         stack_tags=stack_tags)
        self.env_ctx = env_ctx
        self.set_aws_name('CodeDeployApplication', grp_id, cdapp.name)
        self.init_template('CodeDeploy Application')
        self.res_name_prefix = self.create_resource_name_join(name_list=[
            self.env_ctx.get_aws_name(), app_id, grp_id, cdapp.name
        ],
                                                              separator='-',
                                                              camel_case=True)

        # Service Role ARN parameter
        service_role_arn_param = self.create_cfn_parameter(
            param_type='String',
            name='ServiceRoleArn',
            description='The codedeploy service Role to assume.',
            value=role.get_arn(),
        )

        # CodeDeploy Application
        cdapp_resource = troposphere.codedeploy.Application(
            'CodeDeployApplication', ComputePlatform=cdapp.compute_platform)
        self.template.add_resource(cdapp_resource)

        # DeploymentGroup resources
        for deploy_group in cdapp.deployment_groups.values():
            if not deploy_group.is_enabled(): continue

            # Deployment configuration
            deploy_group_logical_id = self.create_cfn_logical_id(
                'DeploymentGroup' + deploy_group.name)
            deployment_dict = {
                'Description': deploy_group.title_or_name,
            }
            if deploy_group.ignore_application_stop_failures:
                deployment_dict[
                    'IgnoreApplicationStopFailures'] = deploy_group.ignore_application_stop_failures
            if deploy_group.revision_location_s3:
                s3bucket = get_model_obj_from_ref(
                    deploy_group.revision_location_s3.bucket,
                    self.paco_ctx.project)
                deployment_dict['Revision'] = {
                    'S3Location': {
                        'Bucket': s3bucket.get_aws_name(),
                        'Key': deploy_group.revision_location_s3.key,
                    },
                    'RevisionType': 'S3'
                }
                if deploy_group.revision_location_s3.bundle_type:
                    deployment_dict['Revision']['S3Location'][
                        'BundleType'] = deploy_group.revision_location_s3.bundle_type

            cfn_export_dict = {
                'Deployment': deployment_dict,
                'ApplicationName': troposphere.Ref(cdapp_resource),
                'ServiceRoleArn': troposphere.Ref(service_role_arn_param),
            }
            if deploy_group.autoscalinggroups:
                cfn_export_dict['AutoScalingGroups'] = []
                for asg_ref in deploy_group.autoscalinggroups:
                    asg = get_model_obj_from_ref(asg_ref,
                                                 self.paco_ctx.project)
                    cfn_export_dict['AutoScalingGroups'].append(
                        asg.get_aws_name())

            deploy_group_resource = troposphere.codedeploy.DeploymentGroup.from_dict(
                deploy_group_logical_id, cfn_export_dict)
            self.template.add_resource(deploy_group_resource)
            deploy_group_resource.DependsOn = []
            deploy_group_resource.DependsOn.append(cdapp_resource.title)

            # User-defined Policies
            for policy in deploy_group.role_policies:
                policy_name = self.create_resource_name_join(
                    name_list=[
                        self.res_name_prefix, 'CodeDeploy', deploy_group.name,
                        policy.name
                    ],
                    separator='-',
                    filter_id='IAM.Policy.PolicyName',
                    hash_long_names=True,
                    camel_case=True)
                statement_list = []
                for statement in policy.statement:
                    action_list = []
                    for action in statement.action:
                        action_parts = action.split(':')
                        action_list.append(
                            Action(action_parts[0], action_parts[1]))
                    statement_list.append(
                        Statement(Effect=statement.effect,
                                  Action=action_list,
                                  Resource=statement.resource))
                policy_resource = troposphere.iam.PolicyType(
                    title=self.create_cfn_logical_id('CodeDeployPolicy' +
                                                     policy.name,
                                                     camel_case=True),
                    PolicyName=policy_name,
                    PolicyDocument=PolicyDocument(Statement=statement_list, ),
                    Roles=[troposphere.Ref(service_role_resource)])
                self.template.add_resource(policy_resource)
                deploy_group_resource.DependsOn = policy_resource

        # All done, let's go home!
        self.set_template()
    Parameter(
        'Regions',
        Description='Region to search for SecurityGroups, separated by ","',
        Default='us-east-1',
        Type='String'))

#
# Resources
#

update_function_execution_role = t.add_resource(
    iam.Role(
        'LambdaExecutionRole',
        AssumeRolePolicyDocument=Policy(Statement=[
            Statement(Effect=Allow,
                      Action=[awacs.sts.AssumeRole],
                      Principal=Principal('Service', ['lambda.amazonaws.com']))
        ]),
        ManagedPolicyArns=[
            'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
        ],
        Policies=[
            iam.Policy(PolicyName='AllowModifySecurityGroup',
                       PolicyDocument=Policy(
                           Version='2012-10-17',
                           Statement=[
                               Statement(
                                   Effect=Allow,
                                   Action=[
                                       awacs.ec2.DescribeSecurityGroups,
                                       awacs.ec2.AuthorizeSecurityGroupIngress,
Exemplo n.º 12
0
    def script_manager_ecr_deploy(self, ecr_deploy_group, asg_dict, asg_config, template):
        policy_statements = []
        for ecr_deploy_name in ecr_deploy_group.keys():
            ecr_deploy = ecr_deploy_group[ecr_deploy_name]
            if ecr_deploy == None:
                continue

            if ecr_deploy and len(ecr_deploy.release_phase.ecs) > 0:
                pull_repos = []
                push_repos = []
                for repository in ecr_deploy.repositories:
                    source_ecr_obj = get_model_obj_from_ref(repository.source_repo, self.paco_ctx.project)
                    source_env = get_parent_by_interface(source_ecr_obj, schemas.IEnvironmentRegion)
                    source_account_id = self.paco_ctx.get_ref(source_env.network.aws_account+".id")

                    dest_ecr_obj = get_model_obj_from_ref(repository.dest_repo, self.paco_ctx.project)
                    dest_env = get_parent_by_interface(dest_ecr_obj, schemas.IEnvironmentRegion)
                    dest_account_id = self.paco_ctx.get_ref(dest_env.network.aws_account+".id")

                    pull_repo_arn = f'arn:aws:ecr:{source_env.region}:{source_account_id}:repository/{source_ecr_obj.repository_name}'
                    push_repo_arn = f'arn:aws:ecr:{dest_env.region}:{dest_account_id}:repository/{dest_ecr_obj.repository_name}'
                    pull_repos.append(pull_repo_arn)
                    push_repos.append(push_repo_arn)

                policy_statements.append(
                    Statement(
                        Sid=f'ScriptManagerECRDeployPull',
                        Effect=Allow,
                        Action=[
                            Action('ecr', 'GetDownloadUrlForLayer'),
                            Action('ecr', 'BatchGetImage'),
                        ],
                        Resource=pull_repos
                    )
                )

                policy_statements.append(
                    Statement(
                        Sid=f'ScriptManagerECRDeployPush',
                        Effect=Allow,
                        Action=[
                            Action('ecr', 'GetDownloadUrlForLayer'),
                            Action('ecr', 'BatchCheckLayerAvailability'),
                            Action('ecr', 'PutImage'),
                            Action('ecr', 'InitiateLayerUpload'),
                            Action('ecr', 'UploadLayerPart'),
                            Action('ecr', 'CompleteLayerUpload'),
                        ],
                        Resource=push_repos
                    )
                )
                iam_cluster_cache = []
                idx = 0
                for command in ecr_deploy.release_phase.ecs:
                    service_obj = get_model_obj_from_ref(command.service, self.paco_ctx.project)
                    ecs_services_obj = get_parent_by_interface(service_obj, schemas.IECSServices)
                    ecs_release_phase_cluster_arn_param = self.create_cfn_parameter(
                        param_type='String',
                        name=f'ECSReleasePhaseClusterArn{idx}',
                        description=f'ECS Release Phase Cluster Arn {idx}',
                        value=ecs_services_obj.cluster + '.arn'
                    )
                    ecs_release_phase_cluster_name_param = self.create_cfn_parameter(
                        param_type='String',
                        name=f'ECSReleasePhaseClusterName{idx}',
                        description=f'ECS Release Phase Cluster Name {idx}',
                        value=ecs_services_obj.cluster + '.name'
                    )
                    ecs_release_phase_service_name_param = self.create_cfn_parameter(
                        param_type='String',
                        name=f'ECSReleasePhaseServiceName{idx}',
                        description=f'ECS Release Phase Cluster Name {idx}',
                        value=command.service + '.name'
                    )
                    ecs_cluster_asg_tag = troposphere.autoscaling.Tag(
                        f'PACO_CB_RP_ECS_CLUSTER_ID_{idx}',
                        troposphere.Ref(ecs_release_phase_cluster_name_param),
                        True
                    )
                    ecs_service_asg_tag = troposphere.autoscaling.Tag(
                        f'PACO_CB_RP_ECS_SERVICE_ID_{idx}',
                        troposphere.Ref(ecs_release_phase_service_name_param),
                        True
                    )
                    asg_dict['Tags'].append(ecs_cluster_asg_tag)
                    asg_dict['Tags'].append(ecs_service_asg_tag)


                    if ecs_services_obj.cluster not in iam_cluster_cache:
                        policy_statements.append(
                            Statement(
                                Sid=f'ECSReleasePhaseSSMSendCommand{idx}',
                                Effect=Allow,
                                Action=[
                                    Action('ssm', 'SendCommand'),
                                ],
                                Resource=[ 'arn:aws:ec2:*:*:instance/*' ],
                                Condition=Condition(
                                    StringLike({
                                        'ssm:resourceTag/Paco-ECSCluster-Name': troposphere.Ref(ecs_release_phase_cluster_name_param)
                                    })
                                )
                            )
                        )

                        policy_statements.append(
                            Statement(
                                Sid=f'ECSRelasePhaseClusterAccess{idx}',
                                Effect=Allow,
                                Action=[
                                    Action('ecs', 'DescribeServices'),
                                    Action('ecs', 'RunTask'),
                                    Action('ecs', 'StopTask'),
                                    Action('ecs', 'DescribeContainerInstances'),
                                    Action('ecs', 'ListTasks'),
                                    Action('ecs', 'DescribeTasks'),
                                ],
                                Resource=[ '*' ],
                                Condition=Condition(
                                    StringEquals({
                                        'ecs:cluster': troposphere.Ref(ecs_release_phase_cluster_arn_param)
                                    })
                                )
                            )
                        )
                        iam_cluster_cache.append(ecs_services_obj.cluster)

                    idx += 1

                policy_statements.append(
                    Statement(
                        Sid='ECSReleasePhaseSSMAutomationExecution',
                        Effect=Allow,
                            Action=[
                            Action('ssm', 'StartAutomationExecution'),
                            Action('ssm', 'StopAutomationExecution'),
                            Action('ssm', 'GetAutomationExecution'),
                        ],
                        Resource=[ 'arn:aws:ssm:::automation-definition/' ]
                    )
                )
                # ECS Policies
                policy_statements.append(
                    Statement(
                        Sid='ECSRelasePhaseECS',
                        Effect=Allow,
                        Action=[
                            Action('ecs', 'DescribeTaskDefinition'),
                            Action('ecs', 'DeregisterTaskDefinition'),
                            Action('ecs', 'RegisterTaskDefinition'),
                            Action('ecs', 'ListTagsForResource'),
                            Action('ecr', 'DescribeImages')
                        ],
                        Resource=[ '*' ]
                    )
                )

                policy_statements.append(
                    Statement(
                        Sid=f'ECSReleasePhaseSSMSendCommandDocument',
                        Effect=Allow,
                        Action=[
                            Action('ssm', 'SendCommand'),
                        ],
                        Resource=[ f'arn:aws:ssm:{self.aws_region}:{self.account_ctx.get_id()}:document/paco_ecs_docker_exec' ]
                    )
                )
                policy_statements.append(
                    Statement(
                        Sid='ECSReleasePhaseSSMCore',
                        Effect=Allow,
                        Action=[
                            Action('ssm', 'ListDocuments'),
                            Action('ssm', 'ListDocumentVersions'),
                            Action('ssm', 'DescribeDocument'),
                            Action('ssm', 'GetDocument'),
                            Action('ssm', 'DescribeInstanceInformation'),
                            Action('ssm', 'DescribeDocumentParameters'),
                            Action('ssm', 'CancelCommand'),
                            Action('ssm', 'ListCommands'),
                            Action('ssm', 'ListCommandInvocations'),
                            Action('ssm', 'DescribeAutomationExecutions'),
                            Action('ssm', 'DescribeInstanceProperties'),
                            Action('ssm', 'GetCommandInvocation'),
                            Action('ec2', 'DescribeInstanceStatus'),
                            Action('ecr', 'GetAuthorizationToken')
                        ],
                        Resource=[ '*' ]
                    )
                )

                policy_statements.append(
                    Statement(
                        Sid='IAMPassRole',
                        Effect=Allow,
                        Action=[
                            Action('iam', 'passrole')
                        ],
                        Resource=[ '*' ]
                    )
                )
                ecs_release_phase_project_policy_res = troposphere.iam.ManagedPolicy(
                    title='ECSReleasePhase',
                    PolicyDocument=PolicyDocument(
                        Version="2012-10-17",
                        Statement=policy_statements
                    ),
                    Roles=[self.instance_iam_role_name]
                )
                template.add_resource(ecs_release_phase_project_policy_res)
Exemplo n.º 13
0
    def script_manager_ecs(self, ecs_group, asg_dict, asg_config, template):
        idx=0
        policy_statements = []
        for ecs_name in ecs_group.keys():
            ecs = ecs_group[ecs_name]
            if ecs == None:
                continue

            ecs_script_manager_cluster_arn_param = self.create_cfn_parameter(
                param_type='String',
                name=f'ECSScriptManagerClusterArn{idx}',
                description=f'ECS Script Manager Cluster Arn {idx}',
                value=ecs.cluster + '.arn'
            )
            ecs_cluster_tag = troposphere.autoscaling.Tag(
                f'paco:script_manager:ecs:{ecs_name}:cluster:arn',
                troposphere.Ref(ecs_script_manager_cluster_arn_param),
                True
            )
            asg_dict['Tags'].append(ecs_cluster_tag)

            policy_statements.append(
                Statement(
                    Sid=f'ECSScriptManagerClusterAccess{idx}',
                    Effect=Allow,
                    Action=[
                        Action('ecs', 'UpdateService'),
                        Action('ecs', 'DescribeServices'),
                        Action('ecs', 'ListServices'),
                        Action('ecs', 'RunTask'),
                        Action('ecs', 'StopTask'),
                        Action('ecs', 'DescribeContainerInstances'),
                        Action('ecs', 'ListTasks'),
                        Action('ecs', 'DescribeTasks'),
                        Action('ec2', 'DescribeInstances'),
                    ],
                    Resource=[ '*' ],
                    Condition=Condition(
                        StringEquals({
                            'ecs:cluster': troposphere.Ref(ecs_script_manager_cluster_arn_param)
                        })
                    )
                )
            )
            policy_statements.append(
                Statement(
                    Sid=f'ECSScriptManagerClusterEC2Access{idx}',
                    Effect=Allow,
                    Action=[
                        Action('ec2', 'DescribeInstances'),
                    ],
                    Resource=[ '*' ]
                )
            )

            idx += 1

        script_manager_ecs_policy_res = troposphere.iam.ManagedPolicy(
            title='ScriptManagerECS',
            PolicyDocument=PolicyDocument(
                Version="2012-10-17",
                Statement=policy_statements
            ),
            Roles=[self.instance_iam_role_name]
        )
        template.add_resource(script_manager_ecs_policy_res)
Exemplo n.º 14
0
    def __init__(self, stack, paco_ctx):
        super().__init__(
            stack,
            paco_ctx,
            iam_capabilities=["CAPABILITY_NAMED_IAM"],
        )
        eventsrule = stack.resource
        config_ref = eventsrule.paco_ref_parts
        self.set_aws_name('EventsRule', self.resource_group_name,
                          self.resource_name)

        self.notification_groups = {}

        # Init a Troposphere template
        self.init_template('CloudWatch EventsRule')

        if eventsrule.is_enabled() == False:
            return

        # Parameters
        schedule_expression_param = None
        if eventsrule.schedule_expression:
            schedule_expression_param = self.create_cfn_parameter(
                param_type='String',
                name='ScheduleExpression',
                description='ScheduleExpression for the Event Rule.',
                value=eventsrule.schedule_expression,
            )
        description_param = self.create_cfn_parameter(
            param_type='String',
            name='EventDescription',
            description='Description for the Event Rule.',
            value=eventsrule.description,
        )

        # Monitoring Target
        monitoring = self.resource.monitoring
        if monitoring != None and monitoring.is_enabled() == True:
            notifications = None
            if monitoring.notifications != None and len(
                    monitoring.notifications.keys()) > 0:
                notifications = monitoring.notifications
            else:
                app_config = get_parent_by_interface(self.resource,
                                                     schemas.IApplication)
                notifications = app_config.notifications

            if notifications != None and len(notifications.keys()) > 0:
                # Create the CF Param for the SNS ARN we need to Publish to
                notify_param_cache = []
                for notify_group_name in notifications.keys():
                    for sns_group_name in notifications[
                            notify_group_name].groups:
                        notify_param = self.create_notification_param(
                            sns_group_name)
                        # Only append if the are unique
                        if notify_param not in notify_param_cache:
                            eventsrule.targets.append(notify_param)
                            notify_param_cache.append(notify_param)

        # Targets
        targets = []
        self.target_params = {}
        target_invocation_role_resource = None
        for index in range(0, len(eventsrule.targets)):
            target = eventsrule.targets[index]
            # Target Parameters
            target_name = 'Target{}'.format(index)

            # Target CFN Parameters
            # Check if we already have a parameter object
            target_policy_actions = None
            if isinstance(target, troposphere.Parameter):
                self.target_params[target_name + 'Arn'] = target
            else:
                self.target_params[target_name +
                                   'Arn'] = self.create_cfn_parameter(
                                       param_type='String',
                                       name=target_name + 'Arn',
                                       description=target_name +
                                       ' Arn for the Events Rule.',
                                       value=target.target + '.arn',
                                   )

                # If the target is a reference, get the target object from the model
                # to check what type of resource we need to configure for
                target_ref = Reference(target.target)
                if target_ref.parts[-1] == 'project' and target_ref.parts[
                        -3] == 'build':
                    codebuild_target_ref = f'paco.ref {".".join(target_ref.parts[:-1])}'
                    target_model_obj = get_model_obj_from_ref(
                        codebuild_target_ref, self.paco_ctx.project)
                else:
                    target_model_obj = get_model_obj_from_ref(
                        target.target, self.paco_ctx.project)

                # Lambda Policy Actions
                if schemas.IDeploymentPipelineBuildCodeBuild.providedBy(
                        target_model_obj):
                    # CodeBuild Project
                    target_policy_actions = [awacs.codebuild.StartBuild]
                elif schemas.ILambda.providedBy(target_model_obj):
                    # Lambda Function
                    target_policy_actions = [awacs.awslambda.InvokeFunction]

            self.target_params[target_name] = self.create_cfn_parameter(
                param_type='String',
                name=target_name,
                description=target_name + ' for the Event Rule.',
                value=target_name,
            )

            # IAM Role Polcies by Resource type
            if target_policy_actions != None:
                # IAM Role Resources to allow Event to invoke Target
                target_invocation_role_resource = troposphere.iam.Role(
                    'TargetInvocationRole',
                    AssumeRolePolicyDocument=Policy(
                        Version='2012-10-17',
                        Statement=[
                            Statement(Effect=Allow,
                                      Action=[awacs.sts.AssumeRole],
                                      Principal=Principal(
                                          'Service', ['events.amazonaws.com']))
                        ],
                    ),
                    Policies=[
                        troposphere.iam.Policy(
                            PolicyName="TargetInvocation",
                            PolicyDocument=Policy(
                                Version='2012-10-17',
                                Statement=[
                                    Statement(
                                        Effect=Allow,
                                        Action=target_policy_actions,
                                        Resource=[
                                            troposphere.Ref(
                                                self.target_params[target_name
                                                                   + 'Arn'])
                                        ],
                                    )
                                ]))
                    ],
                )
                self.template.add_resource(target_invocation_role_resource)

            # Create Target CFN Resources
            cfn_export_dict = {
                'Arn':
                troposphere.Ref(self.target_params[target_name + 'Arn']),
                'Id': troposphere.Ref(self.target_params[target_name])
            }

            if target_invocation_role_resource != None:
                cfn_export_dict['RoleArn'] = troposphere.GetAtt(
                    target_invocation_role_resource, 'Arn')
            if hasattr(target, 'input_json') and target.input_json != None:
                cfn_export_dict['Input'] = target.input_json

            # Events Rule Targets
            targets.append(cfn_export_dict)

        # Events Rule Resource
        # The Name is needed so that a Lambda can be created and it's Lambda ARN output
        # can be supplied as a Parameter to this Stack and a Lambda Permission can be
        # made with the Lambda. Avoids circular dependencies.
        name = create_event_rule_name(eventsrule)
        if eventsrule.enabled_state:
            enabled_state = 'ENABLED'
        else:
            enabled_state = 'DISABLED'

        events_rule_dict = {
            'Name': name,
            'Description': troposphere.Ref(description_param),
            'Targets': targets,
            'State': enabled_state
        }

        if target_invocation_role_resource != None:
            events_rule_dict['RoleArn'] = troposphere.GetAtt(
                target_invocation_role_resource, 'Arn')

        if schedule_expression_param != None:
            events_rule_dict['ScheduleExpression'] = troposphere.Ref(
                schedule_expression_param)
        elif eventsrule.event_pattern != None:
            source_value_list = []
            project_name_list = []
            for pattern_source in eventsrule.event_pattern.source:
                if is_ref(pattern_source):
                    source_obj = get_model_obj_from_ref(
                        pattern_source, self.paco_ctx.project)
                    if schemas.IDeploymentPipelineBuildCodeBuild.providedBy(
                            source_obj):
                        source_value_list.append('aws.codebuild')
                        project_name_list.append(
                            source_obj._stack.template.get_project_name())
                    else:
                        raise InvalidEventsRuleEventPatternSource(
                            pattern_source)
                else:
                    source_value_list.append(pattern_source)

            if len(project_name_list) > 0:
                eventsrule.event_pattern.detail[
                    'project-name'] = project_name_list

            event_pattern_dict = {
                'source':
                source_value_list,
                'detail-type':
                utils.obj_to_dict(eventsrule.event_pattern.detail_type),
                'detail':
                utils.obj_to_dict(eventsrule.event_pattern.detail),
            }
            event_pattern_yaml = yaml.dump(event_pattern_dict)
            events_rule_dict['EventPattern'] = yaml.load(event_pattern_yaml)
        else:
            # Defaults to a CodePipeline events rule
            event_pattern_yaml = """
source:
    - aws.codepipeline
detail-type:
    - 'CodePipeline Pipeline Execution State Change'
detail:
    state:
    - STARTED
"""
            events_rule_dict['EventPattern'] = yaml.load(event_pattern_yaml)

        event_rule_resource = troposphere.events.Rule.from_dict(
            'EventRule', events_rule_dict)
        if target_invocation_role_resource != None:
            event_rule_resource.DependsOn = target_invocation_role_resource
        self.template.add_resource(event_rule_resource)

        # Outputs
        self.create_output(
            title="EventRuleId",
            value=troposphere.Ref(event_rule_resource),
            ref=config_ref + '.id',
        )
        self.create_output(
            title="EventRuleArn",
            value=troposphere.GetAtt(event_rule_resource, "Arn"),
            ref=config_ref + '.arn',
        )
Exemplo n.º 15
0
def kms_key_policy(key_use_arns, key_admin_arns):
    """ Creates a key policy for use of a KMS Key.

    key_use_arns is a list of arns that should have access to use the KMS
    key.
    """

    root_arn = Join(":", ["arn:aws:iam:", Ref("AWS::AccountId"), "root"])

    statements = []
    statements.append(
        Statement(Sid="Enable IAM User Permissions",
                  Effect=Allow,
                  Principal=AWSPrincipal(root_arn),
                  Action=[
                      Action("kms", "*"),
                  ],
                  Resource=["*"]))
    statements.append(
        Statement(Sid="Allow use of the key",
                  Effect=Allow,
                  Principal=AWSPrincipal(key_use_arns),
                  Action=[
                      awacs.kms.Encrypt,
                      awacs.kms.Decrypt,
                      awacs.kms.ReEncrypt,
                      awacs.kms.GenerateDataKey,
                      awacs.kms.GenerateDataKeyWithoutPlaintext,
                      awacs.kms.DescribeKey,
                  ],
                  Resource=["*"]))
    statements.append(
        Statement(Sid="Allow attachment of persistent resources",
                  Effect=Allow,
                  Principal=AWSPrincipal(key_use_arns),
                  Action=[
                      awacs.kms.CreateGrant,
                      awacs.kms.ListGrants,
                      awacs.kms.RevokeGrant,
                  ],
                  Resource=["*"],
                  Condition=Condition(Bool("kms:GrantIsForAWSResource",
                                           True))))
    statements.append(
        Statement(
            Sid="Allow access for Key Administrators",
            Effect=Allow,
            Principal=AWSPrincipal(key_admin_arns),
            Action=[
                Action("kms", "Create*"),
                Action("kms", "Describe*"),
                Action("kms", "Enable*"),
                Action("kms", "List*"),
                Action("kms", "Put*"),
                Action("kms", "Update*"),
                Action("kms", "Revoke*"),
                Action("kms", "Disable*"),
                Action("kms", "Get*"),
                Action("kms", "Delete*"),
                Action("kms", "ScheduleKeyDeletion"),
                Action("kms", "CancelKeyDeletion"),
            ],
            Resource=["*"],
        ))

    return Policy(Version="2012-10-17",
                  Id="key-default-1",
                  Statement=statements)
Exemplo n.º 16
0
            "EC2Principal": "ec2.amazonaws.com",
            "OpsWorksPrincipal": "opsworks.amazonaws.com",
        },
    },
)

t.add_resource(
    Role(
        "WebServerRole",
        AssumeRolePolicyDocument=PolicyDocument(Statement=[
            Statement(
                Effect=Allow,
                Action=[AssumeRole],
                Principal=Principal(
                    "Service",
                    [
                        FindInMap("Region2Principal", Ref("AWS::Region"),
                                  "EC2Principal")
                    ],
                ),
            )
        ]),
        Path="/",
    ))

t.add_resource(
    IAMPolicy(
        "WebServerRolePolicy",
        PolicyName="WebServerRole",
        PolicyDocument=PolicyDocument(Statement=[
            Statement(
Exemplo n.º 17
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        self.template.add_version('2010-09-09')
        self.template.add_description('Terraform State Resources')

        # Conditions
        for i in ['BucketName', 'TableName']:
            template.add_condition(
                "%sOmitted" % i,
                Or(Equals(variables[i].ref, ''),
                   Equals(variables[i].ref, 'undefined')))

        # Resources
        terraformlocktable = template.add_resource(
            dynamodb.Table(
                'TerraformStateTable',
                AttributeDefinitions=[
                    dynamodb.AttributeDefinition(AttributeName='LockID',
                                                 AttributeType='S')
                ],
                KeySchema=[
                    dynamodb.KeySchema(AttributeName='LockID', KeyType='HASH')
                ],
                ProvisionedThroughput=dynamodb.ProvisionedThroughput(
                    ReadCapacityUnits=2, WriteCapacityUnits=2),
                TableName=If('TableNameOmitted', NoValue,
                             variables['TableName'].ref)))
        template.add_output(
            Output('%sName' % terraformlocktable.title,
                   Description='Name of DynamoDB table for Terraform state',
                   Value=terraformlocktable.ref()))

        terraformstatebucket = template.add_resource(
            s3.Bucket(
                'TerraformStateBucket',
                AccessControl=s3.Private,
                BucketName=If('BucketNameOmitted', NoValue,
                              variables['BucketName'].ref),
                LifecycleConfiguration=s3.LifecycleConfiguration(Rules=[
                    s3.LifecycleRule(NoncurrentVersionExpirationInDays=90,
                                     Status='Enabled')
                ]),
                VersioningConfiguration=s3.VersioningConfiguration(
                    Status='Enabled')))
        template.add_output(
            Output('%sName' % terraformstatebucket.title,
                   Description='Name of bucket storing Terraform state',
                   Value=terraformstatebucket.ref()))
        template.add_output(
            Output('%sArn' % terraformstatebucket.title,
                   Description='Arn of bucket storing Terraform state',
                   Value=terraformstatebucket.get_att('Arn')))

        managementpolicy = template.add_resource(
            iam.ManagedPolicy(
                'ManagementPolicy',
                Description='Managed policy for Terraform state management.',
                Path='/',
                PolicyDocument=PolicyDocument(
                    Version='2012-10-17',
                    Statement=[
                        # https://www.terraform.io/docs/backends/types/s3.html#s3-bucket-permissions
                        Statement(
                            Action=[awacs.s3.ListBucket],
                            Effect=Allow,
                            Resource=[terraformstatebucket.get_att('Arn')]),
                        Statement(
                            Action=[awacs.s3.GetObject, awacs.s3.PutObject],
                            Effect=Allow,
                            Resource=[
                                Join('', [
                                    terraformstatebucket.get_att('Arn'), '/*'
                                ])
                            ]),
                        Statement(Action=[
                            awacs.dynamodb.GetItem, awacs.dynamodb.PutItem,
                            awacs.dynamodb.DeleteItem
                        ],
                                  Effect=Allow,
                                  Resource=[terraformlocktable.get_att('Arn')])
                    ])))
        template.add_output(
            Output('PolicyArn',
                   Description='Managed policy Arn',
                   Value=managementpolicy.ref()))
Exemplo n.º 18
0
    def __init__(self, stack, paco_ctx,):
        rds_config = stack.resource
        config_ref = rds_config.paco_ref_parts
        super().__init__(stack, paco_ctx, iam_capabilities=["CAPABILITY_IAM"])
        self.set_aws_name('RDS', self.resource_group_name, self.resource.name)
        self.init_template('RDS')
        template = self.template
        if not rds_config.is_enabled(): return

        rds_logical_id = 'PrimaryDBInstance'

        # DB Subnet Group
        db_subnet_id_list_param = self.create_cfn_parameter(
            param_type='List<AWS::EC2::Subnet::Id>',
            name='DBSubnetIdList',
            description='The list of subnet IDs where this database will be provisioned.',
            value=rds_config.segment+'.subnet_id_list',
        )
        db_subnet_group_res = troposphere.rds.DBSubnetGroup(
            title='DBSubnetGroup',
            template =template,
            DBSubnetGroupDescription=troposphere.Ref('AWS::StackName'),
            SubnetIds=troposphere.Ref(db_subnet_id_list_param),
        )

        # DB Parameter Group
        engine_major_version = None
        if rds_config.parameter_group == None:
            # No Parameter Group supplied, create one
            engine_major_version = '.'.join(rds_config.engine_version.split('.')[0:2])
            param_group_family = gen_vocabulary.rds_engine_versions[rds_config.engine][rds_config.engine_version]['param_group_family']
            dbparametergroup_ref = troposphere.rds.DBParameterGroup(
                "DBParameterGroup",
                template = template,
                Family=param_group_family,
                Description=troposphere.Ref('AWS::StackName')
            )
        else:
            # Use an existing Parameter Group
            dbparametergroup_ref = self.create_cfn_parameter(
                name='DBParameterGroupName',
                param_type='String',
                description='DB Parameter Group Name',
                value=rds_config.parameter_group + '.name',
            )

        # Option Group
        option_group_res = None
        if len(rds_config.option_configurations) > 0 or (hasattr(rds_config, 'backup_restore_bucket') and rds_config.backup_restore_bucket != None):
            option_group_dict = {
                'EngineName': rds_config.engine,
                'MajorEngineVersion': engine_major_version,
                'OptionGroupDescription': troposphere.Ref('AWS::StackName')
            }
            option_config_list = []
            if len(rds_config.option_configurations) > 0:
                for option_config in rds_config.option_configurations:
                    option_config_dict = {
                        'OptionName': option_config.option_name,
                    }
                    if len(option_config.option_settings) > 0:
                        option_config_dict['OptionSettings'] = []
                        idx = 0
                        for option_setting in option_config.option_settings:
                            option_value = option_setting.value
                            if references.is_ref(option_setting.value):
                                # Use an existing Parameter Group
                                option_setting_value_param = self.create_cfn_parameter(
                                    name=f'OptionsGroupValue{idx}',
                                    param_type='String',
                                    description=f'DB Option Settings Value {idx}',
                                    value=option_setting.value
                                )
                                option_value = troposphere.Ref(option_setting_value_param)

                            option_setting_dict = {
                                'Name': option_setting.name,
                                'Value': option_value
                            }
                            option_config_dict['OptionSettings'].append(option_setting_dict)
                    option_config_list.append(option_config_dict)
            if hasattr(rds_config, 'backup_restore_bucket') and rds_config.backup_restore_bucket != None:
                option_config_dict = {
                    'OptionName': 'SQLSERVER_BACKUP_RESTORE',
                    'OptionSettings': []
                }
                # S3 Bucket Arn Param
                backup_restore_bucket_arn_param = self.create_cfn_parameter(
                    name='SQLServerBackupRestoreBucketArn',
                    param_type='String',
                    description=f'DB Option Setting SQLServer Backup Restore Bucket ARN',
                    value=f'{rds_config.backup_restore_bucket}.arn'
                )
                # Create Role for SQLServer Bucket
                sqlserver_backup_restore_role = troposphere.iam.Role(
                    title='SQLServerBackupRestoreRole',
                    template=self.template,
                    AssumeRolePolicyDocument=PolicyDocument(
                        Statement=[
                            Statement(
                                Effect=Allow,
                                Action=[Action("sts", "AssumeRole")],
                                Principal=Principal("Service", "rds.amazonaws.com")
                            )
                        ]
                    ),
                    Policies=[
                        troposphere.iam.Policy(
                            PolicyName="S3BucketAccess",
                            PolicyDocument=Policy(
                                Version='2012-10-17',
                                Statement=[
                                    Statement(
                                        Effect=Allow,
                                        Action=[
                                            awacs.s3.ListBucket,
                                            awacs.s3.GetBucketLocation
                                        ],
                                        Resource=[troposphere.Ref(backup_restore_bucket_arn_param)],
                                    ),
                                    Statement(
                                        Effect=Allow,
                                        Action=[
                                            Action('s3', 'GetObjectMetaData'),
                                            awacs.s3.GetObject,
                                            awacs.s3.PutObject,
                                            awacs.s3.ListMultipartUploadParts,
                                            awacs.s3.AbortMultipartUpload
                                        ],
                                        Resource=[troposphere.Sub("${SQLServerBackupRestoreBucketArn}/*")]
                                    )
                                ]
                            )
                        )
                    ],
                    Path="/",
                )
                option_value = troposphere.GetAtt(sqlserver_backup_restore_role, 'Arn')

                option_setting_dict = {
                    'Name': 'IAM_ROLE_ARN',
                    'Value': option_value
                }
                option_config_dict['OptionSettings'].append(option_setting_dict)
                option_config_list.append(option_config_dict)
            option_group_dict['OptionConfigurations'] = option_config_list

            option_group_res = troposphere.rds.OptionGroup.from_dict(
                'OptionGroup',
                option_group_dict )
            template.add_resource(option_group_res)

        # RDS MultiAZ (Mysql, Postgresql)
        sg_param_ref_list = []
        for sg_ref in rds_config.security_groups:
            sg_hash = utils.md5sum(str_data=sg_ref)
            sg_param = self.create_cfn_parameter(
                param_type='AWS::EC2::SecurityGroup::Id',
                name=self.create_cfn_logical_id('SecurityGroup'+sg_hash),
                description='VPC Security Group to attach to the RDS.',
                value=sg_ref+'.id',
            )
            sg_param_ref_list.append(troposphere.Ref(sg_param))

        db_instance_dict = {
            'Engine': rds_config.engine,
            'EngineVersion': rds_config.engine_version,
            'DBInstanceIdentifier': troposphere.Ref('AWS::StackName'),
            'DBInstanceClass': rds_config.db_instance_type,
            'DBSubnetGroupName': troposphere.Ref(db_subnet_group_res),
            'DBParameterGroupName': troposphere.Ref(dbparametergroup_ref),
            'CopyTagsToSnapshot': True,
            'AllowMajorVersionUpgrade': rds_config.allow_major_version_upgrade,
            'AutoMinorVersionUpgrade': rds_config.auto_minor_version_upgrade,
            'AllocatedStorage': rds_config.storage_size_gb,
            'StorageType': rds_config.storage_type,
            'BackupRetentionPeriod': rds_config.backup_retention_period,
            'Port': rds_config.port,
            'PreferredBackupWindow': rds_config.backup_preferred_window,
            'PreferredMaintenanceWindow': rds_config.maintenance_preferred_window,
            'VPCSecurityGroups': sg_param_ref_list
        }

        if schemas.IRDSMultiAZ.providedBy(rds_config):
            db_instance_dict['MultiAZ'] = rds_config.multi_az


        # License Model
        if rds_config.license_model:
            db_instance_dict['LicenseModel'] = rds_config.license_model

        # Deletion Protection
        if rds_config.deletion_protection:
            db_instance_dict['DeletionProtection'] = rds_config.deletion_protection

        # CloudWatch Logs Exports
        if len(rds_config.cloudwatch_logs_exports) > 0:
            db_instance_dict['EnableCloudwatchLogsExports'] = rds_config.cloudwatch_logs_exports

        # Option Group
        if option_group_res != None:
            db_instance_dict['OptionGroupName'] = troposphere.Ref(option_group_res)

        # DB Snapshot Identifier
        if rds_config.db_snapshot_identifier == '' or rds_config.db_snapshot_identifier == None:
            db_snapshot_id_enabled = False
        else:
            db_snapshot_id_enabled = True
        if db_snapshot_id_enabled == True:
            db_instance_dict['DBSnapshotIdentifier'] = rds_config.db_snapshot_identifier
            # To restore an existing DB from a Snapshot, RDS will need to replace the RDS
            # resource, in which case the DBInstanceIdentifier name CAN NOT be set
            # del db_instance_dict['DBInstanceIdentifier']

        # Username and Passsword
        if db_snapshot_id_enabled == False:
            # Encryption
            if rds_config.storage_encrypted == True:
                db_instance_dict['StorageEncrypted'] = True
            if rds_config.kms_key_id and rds_config.kms_key_id != '':
                db_instance_dict['KmsKeyId'] = rds_config.kms_key_id

            # Username & Password
            db_instance_dict['MasterUsername'] = rds_config.master_username
            if rds_config.secrets_password:
                # Password from Secrets Manager
                sta_logical_id = 'SecretTargetAttachmentRDS'
                secret_arn_param = self.create_cfn_parameter(
                    param_type='String',
                    name='RDSSecretARN',
                    description='The ARN for the secret for the RDS master password.',
                    value=rds_config.secrets_password + '.arn',
                )
                secret_target_attachment_resource = troposphere.secretsmanager.SecretTargetAttachment(
                    title=sta_logical_id,
                    SecretId=troposphere.Ref(secret_arn_param),
                    TargetId=troposphere.Ref(rds_logical_id),
                    TargetType='AWS::RDS::DBInstance'
                )
                template.add_resource(secret_target_attachment_resource)

                db_instance_dict['MasterUserPassword'] = troposphere.Join(
                    '',
                    ['{{resolve:secretsmanager:', troposphere.Ref(secret_arn_param), ':SecretString:password}}' ]
                )
            else:
                master_password_param = self.create_cfn_parameter(
                    param_type='String',
                    name='MasterUserPassword',
                    description='The master user password.',
                    value=rds_config.master_user_password,
                    noecho=True,
                )
                db_instance_dict['MasterUserPassword'] = troposphere.Ref(master_password_param)

        db_instance_res = troposphere.rds.DBInstance.from_dict(
            rds_logical_id,
            db_instance_dict
        )
        template.add_resource(db_instance_res)

        # Outputs
        self.create_output(
            title='DBInstanceName',
            description='DB Instance Name',
            value=troposphere.Ref(db_instance_res),
            ref=config_ref + ".name",
        )
        self.create_output(
            title='RDSEndpointAddress',
            description='RDS Endpoint URL',
            value=troposphere.GetAtt(db_instance_res, 'Endpoint.Address'),
            ref=config_ref + ".endpoint.address",
        )

        # Legacy Route53 Record Set
        if self.paco_ctx.legacy_flag('route53_record_set_2019_10_16') == True:
            if rds_config.is_dns_enabled() == True:
                for dns_config in rds_config.dns_config:
                    dns_hash = utils.md5sum(str_data=(rds_config.hosted_zone+rds_config.domain_name))
                    primary_hosted_zone_id_param = self.create_cfn_parameter(
                        param_type='String',
                        name='DNSHostedZoneId'+dns_hash,
                        description='The hosted zone id to create the Route53 record set.',
                        value=rds_config.primary_hosted_zone+'.id',
                    )
                    record_set_res = troposphere.route53.RecordSetType(
                        title = 'RecordSet'+dns_hash,
                        template = template,
                        Comment = 'RDS Primary DNS',
                        HostedZoneId = troposphere.Ref(primary_hosted_zone_id_param),
                        Name = rds_config.primary_domain_name,
                        Type = 'CNAME',
                        TTL = dns_config.ttl,
                        ResourceRecords = [ troposphere.GetAtt(db_instance_res, 'Endpoint.Address')]
                    )
                    record_set_res.DependsOn = db_instance_res

        # DNS - Route53 Record Set
        if self.paco_ctx.legacy_flag('route53_record_set_2019_10_16') == False:
            if rds_config.is_dns_enabled() == True:
                route53_ctl = self.paco_ctx.get_controller('route53')
                for dns_config in rds_config.dns:
                    route53_ctl.add_record_set(
                        self.account_ctx,
                        self.aws_region,
                        rds_config,
                        enabled=rds_config.is_enabled(),
                        dns=dns_config,
                        record_set_type='CNAME',
                        resource_records=['paco.ref ' + config_ref + '.endpoint.address'],
                        stack_group=self.stack.stack_group,
                        async_stack_provision=True,
                        config_ref=rds_config.paco_ref_parts + '.dns'
                    )
Exemplo n.º 19
0
    def __init__(
        self,
        stack,
        paco_ctx,
    ):
        super().__init__(
            stack,
            paco_ctx,
            iam_capabilities=["CAPABILITY_NAMED_IAM"],
        )
        account_ctx = stack.account_ctx
        aws_region = stack.aws_region
        self.set_aws_name('Lambda', self.resource_group_name,
                          self.resource_name)
        awslambda = self.awslambda = self.stack.resource
        self.init_template('Lambda Function')

        # if not enabled finish with only empty placeholder
        if not awslambda.is_enabled(): return

        # Parameters
        sdb_cache_param = self.create_cfn_parameter(
            name='EnableSDBCache',
            param_type='String',
            description=
            'Boolean indicating whether an SDB Domain will be created to be used as a cache.',
            value=awslambda.sdb_cache)
        function_description_param = self.create_cfn_parameter(
            name='FunctionDescription',
            param_type='String',
            description='A description of the Lamdba Function.',
            value=awslambda.description)
        handler_param = self.create_cfn_parameter(
            name='Handler',
            param_type='String',
            description='The name of the function to call upon execution.',
            value=awslambda.handler)
        runtime_param = self.create_cfn_parameter(
            name='Runtime',
            param_type='String',
            description='The name of the runtime language.',
            value=awslambda.runtime)
        role_arn_param = self.create_cfn_parameter(
            name='RoleArn',
            param_type='String',
            description='The execution role for the Lambda Function.',
            value=awslambda.iam_role.get_arn())
        role_name_param = self.create_cfn_parameter(
            name='RoleName',
            param_type='String',
            description='The execution role name for the Lambda Function.',
            value=awslambda.iam_role.resolve_ref_obj.role_name)
        memory_size_param = self.create_cfn_parameter(
            name='MemorySize',
            param_type='Number',
            description="The amount of memory that your function has access to. Increasing the function's" + \
            " memory also increases its CPU allocation. The default value is 128 MB. The value must be a multiple of 64 MB.",
            value=awslambda.memory_size
        )
        reserved_conc_exec_param = self.create_cfn_parameter(
            name='ReservedConcurrentExecutions',
            param_type='Number',
            description=
            'The number of simultaneous executions to reserve for the function.',
            value=awslambda.reserved_concurrent_executions)
        timeout_param = self.create_cfn_parameter(
            name='Timeout',
            param_type='Number',
            description=
            'The amount of time that Lambda allows a function to run before stopping it. ',
            value=awslambda.timeout)
        layers_param = self.create_cfn_parameter(
            name='Layers',
            param_type='CommaDelimitedList',
            description='List of up to 5 Lambda Layer ARNs.',
            value=','.join(awslambda.layers))

        # create the Lambda resource
        cfn_export_dict = {
            'Description': troposphere.Ref(function_description_param),
            'Handler': troposphere.Ref(handler_param),
            'MemorySize': troposphere.Ref(memory_size_param),
            'Runtime': troposphere.Ref(runtime_param),
            'Role': troposphere.Ref(role_arn_param),
            'Timeout': troposphere.Ref(timeout_param),
        }
        if awslambda.reserved_concurrent_executions:
            cfn_export_dict['ReservedConcurrentExecutions'] = troposphere.Ref(
                reserved_conc_exec_param),

        if len(awslambda.layers) > 0:
            cfn_export_dict['Layers'] = troposphere.Ref(layers_param),

        # Lambda VPC
        if awslambda.vpc_config != None:
            vpc_security_group = self.create_cfn_ref_list_param(
                name='VpcSecurityGroupIdList',
                param_type='List<AWS::EC2::SecurityGroup::Id>',
                description='VPC Security Group Id List',
                value=awslambda.vpc_config.security_groups,
                ref_attribute='id',
            )
            # Segment SubnetList is a Segment stack Output based on availability zones
            segment_ref = awslambda.vpc_config.segments[0] + '.subnet_id_list'
            subnet_list_param = self.create_cfn_parameter(
                name='VpcSubnetIdList',
                param_type='List<AWS::EC2::Subnet::Id>',
                description='VPC Subnet Id List',
                value=segment_ref)
            cfn_export_dict['VpcConfig'] = {
                'SecurityGroupIds': troposphere.Ref(vpc_security_group),
                'SubnetIds': troposphere.Ref(subnet_list_param),
            }

        # Code object: S3 Bucket, inline ZipFile or deploy artifact?
        if awslambda.code.s3_bucket:
            if awslambda.code.s3_bucket.startswith('paco.ref '):
                value = awslambda.code.s3_bucket + ".name"
            else:
                value = awslambda.code.s3_bucket
            s3bucket_param = self.create_cfn_parameter(
                name='CodeS3Bucket',
                description=
                "An Amazon S3 bucket in the same AWS Region as your function. The bucket can be in a different AWS account.",
                param_type='String',
                value=value)
            s3key_param = self.create_cfn_parameter(
                name='CodeS3Key',
                description="The Amazon S3 key of the deployment package.",
                param_type='String',
                value=awslambda.code.s3_key)
            cfn_export_dict['Code'] = {
                'S3Bucket': troposphere.Ref(s3bucket_param),
                'S3Key': troposphere.Ref(s3key_param),
            }
        else:
            zip_path = Path(awslambda.code.zipfile)
            if zip_path.is_file():
                cfn_export_dict['Code'] = {'ZipFile': zip_path.read_text()}
            elif zip_path.is_dir():
                # get S3Bucket/S3Key or if it does not exist, it will create the bucket and artifact
                # and then upload the artifact
                bucket_name, artifact_name = init_lambda_code(
                    self.paco_ctx.paco_buckets,
                    self.stack.resource,
                    awslambda.code.zipfile,
                    self.stack.account_ctx,
                    self.stack.aws_region,
                )
                s3bucket_param = self.create_cfn_parameter(
                    name='CodeS3Bucket',
                    description="The Paco S3 Bucket for configuration",
                    param_type='String',
                    value=bucket_name)
                s3key_param = self.create_cfn_parameter(
                    name='CodeS3Key',
                    description="The Lambda code artifact S3 Key.",
                    param_type='String',
                    value=artifact_name)
                cfn_export_dict['Code'] = {
                    'S3Bucket': troposphere.Ref(s3bucket_param),
                    'S3Key': troposphere.Ref(s3key_param),
                }

        # Environment variables
        var_export = {}
        if awslambda.environment != None and awslambda.environment.variables != None:
            for var in awslambda.environment.variables:
                name = var.key.replace('_', '')
                env_param = self.create_cfn_parameter(
                    name='EnvVar{}'.format(name),
                    param_type='String',
                    description='Env var for {}'.format(name),
                    value=var.value,
                )
                var_export[var.key] = troposphere.Ref(env_param)
            if awslambda.sdb_cache == True:
                var_export['SDB_CACHE_DOMAIN'] = troposphere.Ref(
                    'LambdaSDBCacheDomain')
            if len(awslambda.log_group_names) > 0:
                # Add PACO_LOG_GROUPS Environment Variable
                var_export['PACO_LOG_GROUPS'] = [
                    prefixed_name(awslambda, loggroup_name,
                                  self.paco_ctx.legacy_flag)
                    for loggroup_name in awslambda.log_group_names
                ]
        cfn_export_dict['Environment'] = {'Variables': var_export}

        # Lambda resource
        self.awslambda_resource = troposphere.awslambda.Function.from_dict(
            'Function', cfn_export_dict)
        self.template.add_resource(self.awslambda_resource)

        # SDB Cache with SDB Domain and SDB Domain Policy resources
        if awslambda.sdb_cache == True:
            sdb_domain_resource = troposphere.sdb.Domain(
                title='LambdaSDBCacheDomain',
                template=self.template,
                Description="Lambda Function Domain")
            sdb_policy = troposphere.iam.Policy(
                title='LambdaSDBCacheDomainPolicy',
                template=self.template,
                PolicyName='SDBDomain',
                PolicyDocument=Policy(
                    Version='2012-10-17',
                    Statement=[
                        Statement(
                            Effect=Allow,
                            Action=[Action("sdb", "*")],
                            Resource=[
                                troposphere.Sub(
                                    'arn:aws:sdb:${AWS::Region}:${AWS::AccountId}:domain/${DomainName}',
                                    DomainName=troposphere.Ref(
                                        'LambdaSDBCacheDomain'))
                            ],
                        )
                    ],
                    Roles=troposphere.Ref(role_arn_param)))
            sdb_policy.DependsOn = sdb_domain_resource
            self.awslambda_resource.DependsOn = sdb_domain_resource

        # Permissions
        # SNS Topic Lambda permissions and subscription
        idx = 1
        for sns_topic_ref in awslambda.sns_topics:
            # SNS Topic Arn parameters
            param_name = 'SNSTopicArn%d' % idx
            self.create_cfn_parameter(
                name=param_name,
                param_type='String',
                description='An SNS Topic ARN to grant permission to.',
                value=sns_topic_ref + '.arn')

            # Lambda permission
            troposphere.awslambda.Permission(
                title=param_name + 'Permission',
                template=self.template,
                Action="lambda:InvokeFunction",
                FunctionName=troposphere.GetAtt(self.awslambda_resource,
                                                'Arn'),
                Principal='sns.amazonaws.com',
                SourceArn=troposphere.Ref(param_name),
            )

            # SNS Topic subscription
            sns_topic = get_model_obj_from_ref(sns_topic_ref,
                                               self.paco_ctx.project)
            troposphere.sns.SubscriptionResource(
                title=param_name + 'Subscription',
                template=self.template,
                Endpoint=troposphere.GetAtt(self.awslambda_resource, 'Arn'),
                Protocol='lambda',
                TopicArn=troposphere.Ref(param_name),
                Region=sns_topic.region_name)
            idx += 1

        # Lambda permissions for connected Paco resources

        app = get_parent_by_interface(awslambda, schemas.IApplication)
        for obj in get_all_nodes(app):
            # S3 Bucket notification permission(s)
            if schemas.IS3Bucket.providedBy(obj):
                seen = {}
                if hasattr(obj, 'notifications'):
                    if hasattr(obj.notifications, 'lambdas'):
                        for lambda_notif in obj.notifications.lambdas:
                            if lambda_notif.function == awslambda.paco_ref:
                                # yes, this Lambda gets notification from this S3Bucket
                                group = get_parent_by_interface(
                                    obj, schemas.IResourceGroup)
                                s3_logical_name = self.gen_cf_logical_name(
                                    group.name + obj.name, '_')
                                if s3_logical_name not in seen:
                                    troposphere.awslambda.Permission(
                                        title='S3Bucket' + s3_logical_name,
                                        template=self.template,
                                        Action="lambda:InvokeFunction",
                                        FunctionName=troposphere.GetAtt(
                                            self.awslambda_resource, 'Arn'),
                                        Principal='s3.amazonaws.com',
                                        SourceArn='arn:aws:s3:::' +
                                        obj.get_bucket_name(),
                                    )
                                    seen[s3_logical_name] = True

            # Events Rule permission(s)
            if schemas.IEventsRule.providedBy(obj):
                seen = {}
                for target in obj.targets:
                    target_ref = Reference(target.target)
                    target_ref.set_account_name(account_ctx.get_name())
                    target_ref.set_region(aws_region)
                    lambda_ref = Reference(awslambda.paco_ref)

                    if target_ref.raw == lambda_ref.raw:
                        # yes, the Events Rule has a Target that is this Lambda
                        group = get_parent_by_interface(
                            obj, schemas.IResourceGroup)
                        eventsrule_logical_name = self.gen_cf_logical_name(
                            group.name + obj.name, '_')
                        if eventsrule_logical_name not in seen:
                            rule_name = create_event_rule_name(obj)
                            # rule_name = self.create_cfn_logical_id("EventsRule" + obj.paco_ref)
                            # rule_name = hash_smaller(rule_name, 64)
                            source_arn = 'arn:aws:events:{}:{}:rule/{}'.format(
                                aws_region, account_ctx.id, rule_name)
                            troposphere.awslambda.Permission(
                                title='EventsRule' + eventsrule_logical_name,
                                template=self.template,
                                Action="lambda:InvokeFunction",
                                FunctionName=troposphere.GetAtt(
                                    self.awslambda_resource, 'Arn'),
                                Principal='events.amazonaws.com',
                                SourceArn=source_arn,
                            )
                            seen[eventsrule_logical_name] = True

            # IoT Analytics permission(s)
            if schemas.IIoTAnalyticsPipeline.providedBy(obj):
                seen = {}
                for activity in obj.pipeline_activities.values():
                    if activity.activity_type == 'lambda':
                        target_ref = Reference(activity.function)
                        target_ref.set_account_name(account_ctx.get_name())
                        target_ref.set_region(aws_region)
                        lambda_ref = Reference(awslambda.paco_ref)
                        if target_ref.raw == lambda_ref.raw:
                            # yes, the IoT Analytics Lambda Activity has a ref to this Lambda
                            group = get_parent_by_interface(
                                obj, schemas.IResourceGroup)
                            iotap_logical_name = self.gen_cf_logical_name(
                                group.name + obj.name, '_')
                            if iotap_logical_name not in seen:
                                rule_name = create_event_rule_name(obj)
                                troposphere.awslambda.Permission(
                                    title='IoTAnalyticsPipeline' +
                                    iotap_logical_name,
                                    template=self.template,
                                    Action="lambda:InvokeFunction",
                                    FunctionName=troposphere.GetAtt(
                                        self.awslambda_resource, 'Arn'),
                                    Principal='iotanalytics.amazonaws.com',
                                )
                                seen[iotap_logical_name] = True

        # Log group(s)
        loggroup_function_name = troposphere.Join('', [
            '/aws/lambda/',
            troposphere.Select(
                6,
                troposphere.Split(
                    ':', troposphere.GetAtt(self.awslambda_resource, 'Arn')))
        ])
        loggroup_resources = []
        loggroup_resources.append(
            self.add_log_group(loggroup_function_name, 'lambda'))
        if len(awslambda.log_group_names) > 0:
            # Additional App-specific LogGroups
            for loggroup_name in awslambda.log_group_names:
                # Add LogGroup to the template
                prefixed_loggroup_name = prefixed_name(
                    awslambda, loggroup_name, self.paco_ctx.legacy_flag)
                loggroup_resources.append(
                    self.add_log_group(prefixed_loggroup_name))

        # LogGroup permissions
        log_group_arns = [
            troposphere.Join(':', [
                f'arn:aws:logs:{self.aws_region}:{account_ctx.id}:log-group',
                loggroup_function_name, '*'
            ])
        ]
        log_stream_arns = [
            troposphere.Join(':', [
                f'arn:aws:logs:{self.aws_region}:{account_ctx.id}:log-group',
                loggroup_function_name, 'log-stream', '*'
            ])
        ]
        for loggroup_name in awslambda.log_group_names:
            prefixed_loggroup_name = prefixed_name(awslambda, loggroup_name,
                                                   self.paco_ctx.legacy_flag)
            log_group_arns.append(
                f'arn:aws:logs:{self.aws_region}:{account_ctx.id}:log-group:{prefixed_loggroup_name}:*'
            )
            log_stream_arns.append(
                f'arn:aws:logs:{self.aws_region}:{account_ctx.id}:log-group:{prefixed_loggroup_name}:log-stream:*'
            )

        loggroup_policy_resource = troposphere.iam.ManagedPolicy(
            title='LogGroupManagedPolicy',
            PolicyDocument=Policy(
                Version='2012-10-17',
                Statement=[
                    Statement(
                        Sid='AllowLambdaModifyLogStreams',
                        Effect=Allow,
                        Action=[
                            Action("logs", "CreateLogStream"),
                            Action("logs", "DescribeLogStreams"),
                        ],
                        Resource=log_group_arns,
                    ),
                    Statement(
                        Sid='AllowLambdaPutLogEvents',
                        Effect=Allow,
                        Action=[
                            Action("logs", "PutLogEvents"),
                        ],
                        Resource=log_stream_arns,
                    ),
                ],
            ),
            Roles=[troposphere.Ref(role_name_param)],
        )
        loggroup_policy_resource.DependsOn = loggroup_resources
        self.template.add_resource(loggroup_policy_resource)

        # Outputs
        self.create_output(
            title='FunctionName',
            value=troposphere.Ref(self.awslambda_resource),
            ref=awslambda.paco_ref_parts + '.name',
        )
        self.create_output(
            title='FunctionArn',
            value=troposphere.GetAtt(self.awslambda_resource, 'Arn'),
            ref=awslambda.paco_ref_parts + '.arn',
        )
Exemplo n.º 20
0
    def __init__(self, stack, paco_ctx,):
        rds_aurora = stack.resource
        super().__init__(stack, paco_ctx, iam_capabilities=["CAPABILITY_IAM"])
        self.set_aws_name('RDSAurora', self.resource_group_name, self.resource.name)
        self.init_template('RDSAurora')
        if not rds_aurora.is_enabled(): return

        rds_cluster_logical_id = 'DBCluster'
        db_cluster_dict = rds_aurora.cfn_export_dict
        self.notification_groups = {}

        # DB Subnet Group
        db_subnet_id_list_param = self.create_cfn_parameter(
            param_type='List<AWS::EC2::Subnet::Id>',
            name='DBSubnetIdList',
            description='The list of subnet IDs where this database will be provisioned.',
            value=rds_aurora.segment + '.subnet_id_list',
        )
        db_subnet_group_resource = troposphere.rds.DBSubnetGroup(
            title='DBSubnetGroup',
            template=self.template,
            DBSubnetGroupDescription=troposphere.Ref('AWS::StackName'),
            SubnetIds=troposphere.Ref(db_subnet_id_list_param),
        )
        db_cluster_dict['DBSubnetGroupName'] = troposphere.Ref(db_subnet_group_resource)

        # DB Cluster Parameter Group
        if rds_aurora.cluster_parameter_group == None:
            # If no Cluster Parameter Group supplied then create one
            param_group_family = gen_vocabulary.rds_engine_versions[rds_aurora.engine][rds_aurora.engine_version]['param_group_family']
            cluster_parameter_group_ref = troposphere.rds.DBClusterParameterGroup(
                "DBClusterParameterGroup",
                template=self.template,
                Family=param_group_family,
                Description=troposphere.Ref('AWS::StackName')
            )
        else:
            # Use existing Parameter Group
            cluster_parameter_group_ref = self.create_cfn_parameter(
                name='DBClusterParameterGroupName',
                param_type='String',
                description='DB Cluster Parameter Group Name',
                value=rds_aurora.cluster_parameter_group + '.name',
            )
        db_cluster_dict['DBClusterParameterGroupName'] = troposphere.Ref(cluster_parameter_group_ref)

        # Default DB Parameter Group
        default_dbparametergroup_resource = None
        need_db_pg = False
        default_instance = rds_aurora.default_instance
        for db_instance in rds_aurora.db_instances.values():
            if default_instance.parameter_group == None and db_instance.parameter_group == None:
                need_db_pg = True
        if need_db_pg:
            # create default DB Parameter Group
            param_group_family = gen_vocabulary.rds_engine_versions[rds_aurora.engine][rds_aurora.engine_version]['param_group_family']
            default_dbparametergroup_resource = troposphere.rds.DBParameterGroup(
                "DBParameterGroup",
                template=self.template,
                Family=param_group_family,
                Description=troposphere.Ref('AWS::StackName')
            )

        # Enhanced Monitoring Role
        need_monitoring_role = False
        enhanced_monitoring_role_resource = None
        for db_instance in rds_aurora.db_instances.values():
            enhanced_monitoring_interval = db_instance.get_value_or_default('enhanced_monitoring_interval_in_seconds')
            if enhanced_monitoring_interval != 0:
                need_monitoring_role = True
        if need_monitoring_role:
            enhanced_monitoring_role_resource = troposphere.iam.Role(
                title='MonitoringIAMRole',
                template=self.template,
                AssumeRolePolicyDocument=PolicyDocument(
                    Statement=[
                        Statement(
                            Effect=Allow,
                            Action=[Action("sts", "AssumeRole")],
                            Principal=Principal("Service", "monitoring.rds.amazonaws.com")
                        )
                    ]
                ),
                ManagedPolicyArns=["arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"],
                Path="/",
            )

        # DB Snapshot Identifier
        if rds_aurora.db_snapshot_identifier == '' or rds_aurora.db_snapshot_identifier == None:
            db_snapshot_id_enabled = False
        else:
            db_snapshot_id_enabled = True
        if db_snapshot_id_enabled == True:
            db_cluster_dict['SnapshotIdentifier'] = rds_aurora.db_snapshot_identifier

        # CloudWatch Export Logs
        if len(rds_aurora.cloudwatch_logs_exports) > 0:
            logs_export_list = []
            if 'postgresql' in rds_aurora.cloudwatch_logs_exports:
                logs_export_list.append('postgresql')
            #if 'upgrade' in rds_aurora.cloudwatch_logs_exports:
            #    logs_export_list.append('upgrade')
            db_cluster_dict['EnableCloudwatchLogsExports'] = logs_export_list

        # KMS-CMK key encryption
        if rds_aurora.enable_kms_encryption == True and db_snapshot_id_enabled == False:
            key_policy = Policy(
                Version='2012-10-17',
                Statement=[
                    Statement(
                        Effect=Allow,
                        Action=[Action('kms', '*'),],
                        Principal=Principal("AWS", [f'arn:aws:iam::{self.stack.account_ctx.id}:root']),
                        Resource=['*'],
                    ),
                    Statement(
                        Effect=Allow,
                        Action=[
                            awacs.kms.Encrypt,
                            awacs.kms.Decrypt,
                            Action('kms', 'ReEncrypt*'),
                            Action('kms', 'GenerateDataKey*'),
                            awacs.kms.CreateGrant,
                            awacs.kms.ListGrants,
                            awacs.kms.DescribeKey,
                        ],
                        Principal=Principal('AWS',['*']),
                        Resource=['*'],
                        Condition=Condition([
                            StringEquals({
                                'kms:CallerAccount': f'{self.stack.account_ctx.id}',
                                'kms:ViaService': f'rds.{self.stack.aws_region}.amazonaws.com'
                            })
                        ]),
                    ),
                ],
            )
            kms_key_resource = troposphere.kms.Key(
                title='AuroraKMSCMK',
                template=self.template,
                KeyPolicy=key_policy,
            )
            db_cluster_dict['StorageEncrypted'] = True
            db_cluster_dict['KmsKeyId'] = troposphere.Ref(kms_key_resource)

            kms_key_alias_resource = troposphere.kms.Alias(
                title="AuroraKMSCMKAlias",
                template=self.template,
                AliasName=troposphere.Sub('alias/${' + rds_cluster_logical_id + '}'),
                TargetKeyId=troposphere.Ref(kms_key_resource),
            )
            kms_key_alias_resource.DependsOn = rds_cluster_logical_id

        # Username and Passsword - only if there is no DB Snapshot Identifier
        if db_snapshot_id_enabled == False:
            db_cluster_dict['MasterUsername'] = rds_aurora.master_username
            if rds_aurora.secrets_password:
                # Password from Secrets Manager
                sta_logical_id = 'SecretTargetAttachmentRDS'
                secret_arn_param = self.create_cfn_parameter(
                    param_type='String',
                    name='RDSSecretARN',
                    description='The ARN for the secret for the RDS master password.',
                    value=rds_aurora.secrets_password + '.arn',
                )
                secret_target_attachment_resource = troposphere.secretsmanager.SecretTargetAttachment(
                    title=sta_logical_id,
                    template=self.template,
                    SecretId=troposphere.Ref(secret_arn_param),
                    TargetId=troposphere.Ref(rds_cluster_logical_id),
                    TargetType='AWS::RDS::DBCluster'
                )
                secret_target_attachment_resource.DependsOn = rds_cluster_logical_id
                db_cluster_dict['MasterUserPassword'] = troposphere.Join(
                    '',
                    ['{{resolve:secretsmanager:', troposphere.Ref(secret_arn_param), ':SecretString:password}}' ]
                )
            else:
                master_password_param = self.create_cfn_parameter(
                    param_type='String',
                    name='MasterUserPassword',
                    description='The master user password.',
                    value=rds_aurora.master_user_password,
                    noecho=True,
                )
                db_cluster_dict['MasterUserPassword'] = troposphere.Ref(master_password_param)

        # VPC Security Groups Ids
        sg_param_ref_list = []
        for sg_ref in rds_aurora.security_groups:
            sg_hash = utils.md5sum(str_data=sg_ref)
            sg_param = self.create_cfn_parameter(
                param_type='AWS::EC2::SecurityGroup::Id',
                name=self.create_cfn_logical_id(f'SecurityGroup{sg_hash}'),
                description='VPC Security Group for DB Cluster',
                value=sg_ref + '.id',
            )
            sg_param_ref_list.append(troposphere.Ref(sg_param))
        if len(sg_param_ref_list) > 0:
            db_cluster_dict['VpcSecurityGroupIds'] = sg_param_ref_list

        # Backtracking
        if rds_aurora.backtrack_window_in_seconds > 0:
            db_cluster_dict['BacktrackWindow'] = rds_aurora.backtrack_window_in_seconds
        if rds_aurora.engine_mode == 'serverless':
            # Backtracking is not supported on serverless engine mode
            # db_cluster_dict['BacktrackWindow'] = 0
            db_cluster_dict['ScalingConfiguration'] = {
                'AutoPause': True,
                'MinCapacity': 1,
                'MaxCapacity': 32,
                'SecondsUntilAutoPause': 300
            }
            db_cluster_dict['Engine'] = 'aurora-mysql'

        db_cluster_res = troposphere.rds.DBCluster.from_dict(
            rds_cluster_logical_id,
            db_cluster_dict
        )
        self.template.add_resource(db_cluster_res)

        # Cluster Event Notifications
        if hasattr(rds_aurora, 'cluster_event_notifications'):
            for group in rds_aurora.cluster_event_notifications.groups:
                notif_param = self.create_notification_param(group)
                event_subscription_resource = troposphere.rds.EventSubscription(
                    title=self.create_cfn_logical_id(f"ClusterEventSubscription{group}"),
                    template=self.template,
                    EventCategories=rds_aurora.cluster_event_notifications.event_categories,
                    SourceIds=[troposphere.Ref(db_cluster_res)],
                    SnsTopicArn=troposphere.Ref(notif_param),
                    SourceType='db-cluster',
                )

        # DB Instance(s)
        for db_instance in rds_aurora.db_instances.values():
            logical_name = self.create_cfn_logical_id(db_instance.name)
            if db_instance.external_resource == True:
                # Setup event notifications
                self.set_db_instance_event_notifications(logical_name, db_instance)
                # External instance only needs to output its name
                self.create_output(
                    title=f'DBInstanceName{logical_name}',
                    description=f'DB Instance Name for {logical_name}',
                    value=db_instance.external_instance_name,
                    ref=db_instance.paco_ref_parts + ".name",
                )
                continue
            db_instance_dict = {
                'DBClusterIdentifier': troposphere.Ref(db_cluster_res),
                'DBInstanceClass': db_instance.get_value_or_default('db_instance_type'),
                'DBSubnetGroupName': troposphere.Ref(db_subnet_group_resource),
                'EnablePerformanceInsights': db_instance.get_value_or_default('enable_performance_insights'),
                'Engine': rds_aurora.engine,
                'PubliclyAccessible': db_instance.get_value_or_default('publicly_accessible'),
                'AllowMajorVersionUpgrade': db_instance.get_value_or_default('allow_major_version_upgrade'),
                'AutoMinorVersionUpgrade': db_instance.get_value_or_default('auto_minor_version_upgrade'),
            }

            # Enhanced Monitoring
            enhanced_monitoring_interval = db_instance.get_value_or_default('enhanced_monitoring_interval_in_seconds')
            if enhanced_monitoring_interval != 0:
                db_instance_dict['MonitoringInterval'] = enhanced_monitoring_interval
                db_instance_dict['MonitoringRoleArn'] = troposphere.GetAtt(enhanced_monitoring_role_resource, "Arn")
            if db_instance.availability_zone != None:
                subnet_id_ref = f'{rds_aurora.segment}.az{db_instance.availability_zone}.availability_zone'
                db_instance_subnet_param = self.create_cfn_parameter(
                    param_type='String',
                    name=f'DBInstanceAZ{logical_name}',
                    description=f'Subnet where DB Instance {logical_name} is provisioned',
                    value=subnet_id_ref,
                )
                db_instance_dict['AvailabilityZone'] = troposphere.Ref(db_instance_subnet_param)

            # DB Parameter Group
            if default_instance.parameter_group == None and db_instance.parameter_group == None:
                dbparametergroup_resource = default_dbparametergroup_resource
            elif db_instance.parameter_group != None:
                # Use instance-specific DB Parameter Group
                dbparametergroup_resource = self.create_cfn_parameter(
                    name=f'DBParameterGroupName{logical_name}',
                    param_type='String',
                    description='DB Parameter Group Name',
                    value=db_instance.parameter_group + '.name',
                )
            else:
                # Use default DB Parameter Group
                dbparametergroup_resource = self.create_cfn_parameter(
                    name=f'DBParameterGroupName{logical_name}',
                    param_type='String',
                    description='DB Parameter Group Name',
                    value=default_instance.parameter_group + '.name',
                )
            db_instance_dict['DBParameterGroupName'] = troposphere.Ref(dbparametergroup_resource)

            db_instance_resource = troposphere.rds.DBInstance.from_dict(
                f'DBInstance{logical_name}',
                db_instance_dict
            )
            self.template.add_resource(db_instance_resource)

            # DB Event Notifications
            self.set_db_instance_event_notifications(logical_name, db_instance, db_instance_resource)

            # DB Instance Outputs
            self.create_output(
                title=f'DBInstanceName{logical_name}',
                description=f'DB Instance Name for {logical_name}',
                value=troposphere.Ref(db_instance_resource),
                ref=db_instance.paco_ref_parts + ".name",
            )

        # DB Cluster Outputs
        self.create_output(
            title='DBClusterName',
            description='DB Cluster Name',
            value=troposphere.Ref(db_cluster_res),
            ref=self.resource.paco_ref_parts + ".name",
        )
        self.create_output(
            title='ClusterEndpointAddress',
            description='Cluster Endpoint Address',
            value=troposphere.GetAtt(db_cluster_res, 'Endpoint.Address'),
            ref=self.resource.paco_ref_parts + ".endpoint.address",
        )
        self.create_output(
            title='ClusterEndpointPort',
            description='Cluster Endpoint Port',
            value=troposphere.GetAtt(db_cluster_res, 'Endpoint.Port'),
            ref=self.resource.paco_ref_parts + ".endpoint.port",
        )
        if rds_aurora.engine_mode != 'serverless':
            self.create_output(
                title='ClusterReadEndpointAddress',
                description='Cluster ReadEndpoint Address',
                value=troposphere.GetAtt(db_cluster_res, 'ReadEndpoint.Address'),
                ref=self.resource.paco_ref_parts + ".readendpoint.address",
            )

        # DNS - Route53 Record Set
        if rds_aurora.is_dns_enabled() == True:
            route53_ctl = self.paco_ctx.get_controller('route53')
            for dns in rds_aurora.dns:
                route53_ctl.add_record_set(
                    self.account_ctx,
                    self.aws_region,
                    rds_aurora,
                    enabled=rds_aurora.is_enabled(),
                    dns=dns,
                    record_set_type='CNAME',
                    resource_records=[rds_aurora.paco_ref + '.endpoint.address'],
                    stack_group=self.stack.stack_group,
                    async_stack_provision=True
                )
            for read_dns in rds_aurora.read_dns:
                route53_ctl.add_record_set(
                    self.account_ctx,
                    self.aws_region,
                    rds_aurora,
                    enabled=rds_aurora.is_enabled(),
                    dns=read_dns,
                    record_set_type='CNAME',
                    resource_records=[rds_aurora.paco_ref + '.readendpoint.address'],
                    stack_group=self.stack.stack_group,
                    async_stack_provision=True
                )
         'Effect': 'Allow',
         'Principal': {
             'Service': ['ec2.amazonaws.com']
         },
         'Action': ['sts:AssumeRole']
     }]
 },
 Policies=[
     iam.Policy(PolicyName='GrantCloudwatch',
                PolicyDocument={
                    "Version":
                    "2012-10-17",
                    "Statement": [
                        Statement(Effect=Allow,
                                  Action=[
                                      Action('cloudwatch', '*'),
                                  ],
                                  Resource=['*']),
                    ]
                }),
     iam.Policy(PolicyName='GrantLogs',
                PolicyDocument={
                    "Version":
                    "2012-10-17",
                    "Statement": [
                        Statement(Effect=Allow,
                                  Action=[
                                      Action('logs', '*'),
                                  ],
                                  Resource=["arn:aws:logs:*:*:*"]),
                    ]
Exemplo n.º 22
0
            't2.medium',
            't2.large',
        ],
        ConstraintDescription='must be a valid EC2 T2 instance type.',
    ))

t.add_resource(
    IAMPolicy("MonitoringPolicy",
              PolicyName="AllowSendingDataForMonitoring",
              PolicyDocument=Policy(Statement=[
                  Statement(Effect=Allow,
                            Action=[
                                Action("cloudwatch", "Put*"),
                                Action("logs", "Create*"),
                                Action("logs", "Put*"),
                                Action("logs", "Describe*"),
                                Action("events", "Put*"),
                                Action("firehouse", "Put*"),
                                Action("autoscaling",
                                       "DescribeAutoScalingInstances"),
                            ],
                            Resource=["*"])
              ]),
              Roles=[Ref("Role")]))

t.add_resource(
    ec2.SecurityGroup(
        "SecurityGroup",
        GroupDescription="Allow SSH and TCP/{} access".format(ApplicationPort),
        SecurityGroupIngress=[
            ec2.SecurityGroupRule(
                IpProtocol="tcp",
Exemplo n.º 23
0
    def create_template(self):
        t = self.template

        bucket_arn = Sub("arn:aws:s3:::${StackerBucket}*")
        cloudformation_scope = Sub(
            "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:"
            "stack/${StackerNamespace}-*")
        changeset_scope = "*"

        # This represents the precise IAM permissions that stacker itself
        # needs.
        stacker_policy = iam.Policy(
            PolicyName="Stacker",
            PolicyDocument=Policy(
                Statement=[
                    Statement(
                        Effect="Allow",
                        Resource=[bucket_arn],
                        Action=[
                            awacs.s3.ListBucket,
                            awacs.s3.GetBucketLocation,
                            awacs.s3.CreateBucket]),
                    Statement(
                        Effect="Allow",
                        Resource=[bucket_arn],
                        Action=[
                            awacs.s3.GetObject,
                            awacs.s3.GetObjectAcl,
                            awacs.s3.PutObject,
                            awacs.s3.PutObjectAcl]),
                    Statement(
                        Effect="Allow",
                        Resource=[changeset_scope],
                        Action=[
                            awacs.cloudformation.DescribeChangeSet,
                            awacs.cloudformation.ExecuteChangeSet,
                        ]),
                    Statement(
                        Effect="Deny",
                        Resource=[Ref("AWS::StackId")],
                        Action=[
                            awacs.cloudformation.Action("*")]),
                    Statement(
                        Effect="Allow",
                        Resource=[cloudformation_scope],
                        Action=[
                            awacs.cloudformation.GetTemplate,
                            awacs.cloudformation.CreateChangeSet,
                            awacs.cloudformation.DeleteStack,
                            awacs.cloudformation.CreateStack,
                            awacs.cloudformation.UpdateStack,
                            awacs.cloudformation.DescribeStacks])]))

        user = t.add_resource(
            iam.User(
                "FunctionalTestUser",
                Policies=[
                    stacker_policy]))

        key = t.add_resource(
            iam.AccessKey(
                "FunctionalTestKey",
                Serial=1,
                UserName=Ref(user)))

        t.add_output(Output("User", Value=Ref(user)))
        t.add_output(Output("AccessKeyId", Value=Ref(key)))
        t.add_output(
            Output(
                "SecretAccessKey",
                Value=GetAtt("FunctionalTestKey", "SecretAccessKey")))
Exemplo n.º 24
0
from troposphere import Template
from troposphere.iam import Role

from awacs.aws import Allow, Statement, Principal, Policy
from awacs.sts import AssumeRole

t = Template()

t.add_resource(
    Role('Role2',
         AssumeRolePolicyDocument=Policy(Statement=[
             Statement(Effect=Allow,
                       Action=[AssumeRole],
                       Principal=Principal('Service', ['ec2.amazonaws.com']))
         ])))

print(t.to_yaml())
ud = Base64(Join('\n', [
    "#!/bin/bash",
    "yum install --enablerepo=epel -y git",
    "pip install ansible",
    AnsiblePullCmd,
    "echo '*/10 * * * * {}' > /etc/cron.d/ansible-ull".format(AnsiblePullCmd)
]))

t.add_resource(Role(
    "Role",
    AssumeRolePolicyDocument=Policy(
       Statement=[
          Statement(
              Effect=Allow,
              Action=[AssumeRole],
              Principal=Principal("Service", ["ec2.amazonaws.com"])
          )
       ]
    )
))

t.add_resource(InstanceProfile(
     "InstanceProfile",
     Path="/",
     Roles=[Ref("Role")]
))

t.add_resource(ec2.Instance(
    "instance",
    ImageId="ami-07edebf3b6affeea1",
Exemplo n.º 26
0
def make_simple_assume_statement(*principals):
    return Statement(
        Principal=Principal('Service', principals),
        Effect=Allow,
        Action=[sts.AssumeRole]
    )
Exemplo n.º 27
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        # variables = self.get_variables()
        template.add_version('2010-09-09')
        template.add_description('Kubernetes IAM policies - V1.0.0')

        # Resources
        nodeinstancerole = template.add_resource(
            iam.Role(
                'NodeInstanceRole',
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    'ec2.amazonaws.com'),
                ManagedPolicyArns=[
                    IAM_POLICY_ARN_PREFIX + i for i in [
                        'AmazonEKSWorkerNodePolicy',
                        'AmazonEKS_CNI_Policy',
                        'AmazonEC2ContainerRegistryReadOnly',
                        # SSM agent not shipped ootb
                        # 'AmazonSSMManagedInstanceCore'
                    ]
                ]))
        template.add_output(
            Output('NodeInstanceRole',
                   Description='The node instance role name',
                   Value=nodeinstancerole.ref()))
        template.add_output(
            Output('NodeInstanceRoleArn',
                   Description='The node instance role ARN',
                   Value=nodeinstancerole.get_att('Arn')))

        nodeinstanceprofile = template.add_resource(
            iam.InstanceProfile('NodeInstanceProfile',
                                Path='/',
                                Roles=[nodeinstancerole.ref()]))
        template.add_output(
            Output('NodeInstanceProfile',
                   Description='The node instance profile',
                   Value=nodeinstanceprofile.ref()))
        template.add_output(
            Output('NodeInstanceProfileArn',
                   Description='The node instance profile ARN',
                   Value=nodeinstanceprofile.get_att('Arn')))

        template.add_resource(
            iam.Role(
                'ClusterAutoScalerInstanceRole',
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    'ec2.amazonaws.com'),
                Policies=[
                    iam.Policy(
                        PolicyName='cluster-autoscaler',
                        PolicyDocument=PolicyDocument(
                            Version='2012-10-17',
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.autoscaling.
                                        DescribeAutoScalingGroups,  # noqa
                                        awacs.autoscaling.
                                        DescribeAutoScalingInstances,  # noqa
                                        awacs.autoscaling.DescribeTags,
                                        awacs.autoscaling.
                                        SetDesiredCapacity,  # noqa
                                        awacs.autoscaling.
                                        TerminateInstanceInAutoScalingGroup
                                    ],  # noqa pylint: disable=line-too-long
                                    Effect=Allow,
                                    Resource=['*'])
                            ]))
                ]))
Exemplo n.º 28
0
def generate_cf_template():
    """
    Returns an entire CloudFormation stack by using troposphere to construct
    each piece
    """
    # Header of CloudFormation template
    t = Template()
    t.add_version("2010-09-09")
    t.add_description("Lambda Chat AWS Resources")
    # Paramters
    description = "should match [0-9]+-[a-z0-9]+.apps.googleusercontent.com"
    google_oauth_client_id = t.add_parameter(Parameter(
        "GoogleOAuthClientID",
        AllowedPattern="[0-9]+-[a-z0-9]+.apps.googleusercontent.com",
        Type="String",
        Description="The Client ID of your Google project",
        ConstraintDescription=description
    ))

    website_s3_bucket_name = t.add_parameter(Parameter(
        "WebsiteS3BucketName",
        AllowedPattern="[a-zA-Z0-9\-]*",
        Type="String",
        Description="Name of S3 bucket to store the website in",
        ConstraintDescription="can contain only alphanumeric characters and dashes.",
    ))

    # The SNS topic the website will publish chat messages to
    website_sns_topic = t.add_resource(sns.Topic(
        'WebsiteSnsTopic',
        TopicName='lambda-chat',
        DisplayName='Lambda Chat'
    ))
    t.add_output(Output(
        "WebsiteSnsTopic",
        Description="sns_topic_arn",
        Value=Ref(website_sns_topic),
    ))

    # The IAM Role and Policy the website will assume to publish to SNS
    website_role = t.add_resource(iam.Role(
        "WebsiteRole",
        Path="/",
        AssumeRolePolicyDocument=Policy(
            Statement=[
                Statement(
                    Effect=Allow,
                    Action=[Action("sts", "AssumeRoleWithWebIdentity")],
                    Principal=Principal("Federated", "accounts.google.com"),
                    Condition=Condition(
                        StringEquals(
                            "accounts.google.com:aud",
                            Ref(google_oauth_client_id)
                        )
                    ),
                ),
            ],
        ),
    ))
    t.add_resource(iam.PolicyType(
        "WebsitePolicy",
        PolicyName="lambda-chat-website-policy",
        Roles=[Ref(website_role)],
        PolicyDocument=Policy(
            Version="2012-10-17",
            Statement=[
                Statement(
                    Effect=Allow,
                    Action=[Action("sns", "Publish")],
                    Resource=[
                        Ref(website_sns_topic)
                    ],
                ),
            ],
        )
    ))
    t.add_output(Output(
        "WebsiteRole",
        Description="website_iam_role_arn",
        Value=GetAtt(website_role, "Arn"),
    ))

    website_bucket = t.add_resource(s3.Bucket(
        'WebsiteS3Bucket',
        BucketName=Ref(website_s3_bucket_name),
        WebsiteConfiguration=s3.WebsiteConfiguration(
            ErrorDocument="error.html",
            IndexDocument="index.html"
        )
    ))
    t.add_output(Output(
        "S3Bucket",
        Description="s3_bucket",
        Value=Ref(website_bucket),
    ))
    t.add_resource(s3.BucketPolicy(
        'WebsiteS3BucketPolicy',
        Bucket=Ref(website_bucket),
        PolicyDocument={
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "PublicAccess",
                    "Effect": "Allow",
                    "Principal": "*",
                    "Action": ["s3:GetObject"],
                    "Resource": [{
                        "Fn::Join": [
                            "",
                            [
                                "arn:aws:s3:::",
                                {
                                    "Ref": "WebsiteS3Bucket",
                                },
                                "/*"
                            ]
                        ]
                    }]
                }
            ]
        }
    ))

    return t
Exemplo n.º 29
0
STACK_NAME = cfg['ec2']['stack_name']
SERVER_NAME = cfg['ec2']['server_name']
STREAM_NAME = cfg['ec2']['stream_name']
TWITTER_KEYWORDS = cfg['ec2']['twitter_keywords']
deployment_commithash = '8aebd8fc0c3b62da8bf881b8678467492801022d'

template = Template()
description = 'Twitter Producer Stack'
template.add_description(description)
template.add_version('2010-09-09')

# instance role
instance_policy_doc = Policy(Statement=[
    Statement(Sid='KinesisAccess',
              Effect=Allow,
              Action=[Action('kinesis', '*')],
              Resource=[
                  'arn:aws:kinesis:eu-west-1:749785218022:stream/DevStreamES'
              ]),
    Statement(Sid='LogsAccess',
              Effect=Allow,
              Action=[Action('logs', '*')],
              Resource=['*']),
    Statement(Sid='ReadS3DeploymentBucket',
              Effect=Allow,
              Action=[Action('s3', 'Get*'),
                      Action('s3', 'List*')],
              Resource=[
                  s3.ARN('nicor-dev'),
                  s3.ARN('nicor-dev/*'),
              ])
])
Exemplo n.º 30
0
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.add_version('2010-09-09')
        template.add_description('Kubernetes Master via EKS - V1.0.0')

        # Resources
        ccpsecuritygroup = template.add_resource(
            ec2.SecurityGroup(
                'ClusterControlPlaneSecurityGroup',
                GroupDescription='Cluster communication with worker nodes',
                Tags=[
                    {'Key': Sub('kubernetes.io/cluster/${EksClusterName}'),
                     'Value': 'owned'},
                    {'Key': 'Product',
                     'Value': 'Kubernetes'},
                    {'Key': 'Project',
                     'Value': 'eks'},
                    {'Key': 'Name',
                     'Value': Sub('${EksClusterName}-sg-worker-nodes')}
                ],
                VpcId=variables['VPC'].ref
            )
        )
        template.add_output(
            Output(
                ccpsecuritygroup.title,
                Description='Cluster communication with worker nodes',
                Export=Export(
                    Sub('${AWS::StackName}-ControlPlaneSecurityGroup')
                ),
                Value=ccpsecuritygroup.ref()
            )
        )

        eksservicerole = template.add_resource(
            iam.Role(
                'EksServiceRole',
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    'eks.amazonaws.com'
                ),
                ManagedPolicyArns=[
                    IAM_POLICY_ARN_PREFIX + i for i in [
                        'AmazonEKSClusterPolicy',
                        'AmazonEKSServicePolicy'
                    ]
                ],
                Policies=[
                    iam.Policy(
                        PolicyName='EksServiceRolePolicy',
                        PolicyDocument=PolicyDocument(
                            Statement=[
                                Statement(
                                    Action=[awacs.iam.CreateServiceLinkedRole,
                                            awacs.iam.PutRolePolicy],
                                    Condition=Condition(
                                        StringLike(
                                            'iam:AWSServiceName',
                                            'elasticloadbalancing.amazonaws.com'  # noqa
                                        )
                                    ),
                                    Effect=Allow,
                                    Resource=[
                                        Sub('arn:aws:iam::${AWS::AccountId}:role/'  # noqa
                                            'aws-service-role/'
                                            'elasticloadbalancing.amazonaws.com/'  # noqa
                                            'AWSServiceRoleForElasticLoadBalancing*')  # noqa
                                    ]
                                )
                            ]
                        )
                    )
                ]
            )
        )

        ekscluster = template.add_resource(
            eks.Cluster(
                'EksCluster',
                Name=variables['EksClusterName'].ref,
                Version=variables['EksVersion'].ref,
                RoleArn=eksservicerole.get_att('Arn'),
                ResourcesVpcConfig=eks.ResourcesVpcConfig(
                    SecurityGroupIds=[ccpsecuritygroup.ref()],
                    SubnetIds=variables['EksSubnets'].ref
                )
            )
        )
        template.add_output(
            Output(
                "%sName" % ekscluster.title,
                Description='EKS Cluster Name',
                Export=Export(
                    Sub("${AWS::StackName}-%sName" % ekscluster.title)
                ),
                Value=ekscluster.ref()
            )
        )
        template.add_output(
            Output(
                "%sEndpoint" % ekscluster.title,
                Description='EKS Cluster Endpoint',
                Export=Export(
                    Sub("${AWS::StackName}-%sEndpoint" % ekscluster.title)
                ),
                Value=ekscluster.get_att('Endpoint')
            )
        )

        # Additional Outputs
        template.add_output(
            Output(
                'VpcId',
                Description='EKS Cluster VPC Id',
                Export=Export(
                    Sub('${AWS::StackName}-VpcId')
                ),
                Value=variables['VPC'].ref
            )
        )
        template.add_output(
            Output(
                'Subnets',
                Description='EKS Cluster Subnets',
                Export=Export(
                    Sub('${AWS::StackName}-Subnets')
                ),
                Value=Join(',', variables['EksSubnets'].ref)
            )
        )