def _directory_factory(
     existing_directory_stack_name,
     existing_nlb_stack_name,
     directory_type,
     bucket_name,
     test_resources_dir,
     region,
     ad_admin_password,
     ad_user_password,
 ):
     directory_stack = None
     if existing_directory_stack_name:
         directory_stack_name = existing_directory_stack_name
         directory_stack = CfnStack(name=directory_stack_name,
                                    region=region,
                                    template=None)
         logging.info("Using pre-existing directory stack named %s",
                      directory_stack_name)
     elif created_directory_stacks.get(region, {}).get("directory"):
         directory_stack_name = created_directory_stacks.get(
             region, {}).get("directory")
         directory_stack = CfnStack(name=directory_stack_name,
                                    region=region,
                                    template=None)
         logging.info(
             "Using directory stack named %s created by another test",
             directory_stack_name)
     else:
         directory_stack = _create_directory_stack(
             cfn_stacks_factory,
             request,
             directory_type,
             test_resources_dir,
             ad_admin_password,
             ad_user_password,
             bucket_name,
             region,
             vpc_stacks[region],
         )
         directory_stack_name = directory_stack.name
         created_directory_stacks[region][
             "directory"] = directory_stack_name
         _populate_directory_with_users(directory_stack,
                                        NUM_USERS_TO_CREATE, region)
     # Create NLB that will be used to enable LDAPS
     if existing_nlb_stack_name:
         nlb_stack_name = existing_nlb_stack_name
         logging.info("Using pre-existing NLB stack named %s",
                      nlb_stack_name)
     elif created_directory_stacks.get(region, {}).get("nlb"):
         nlb_stack_name = created_directory_stacks.get(region,
                                                       {}).get("nlb")
         logging.info("Using NLB stack named %s created by another test",
                      nlb_stack_name)
     else:
         nlb_stack_name = _create_nlb_stack(cfn_stacks_factory, request,
                                            directory_stack, region,
                                            test_resources_dir).name
         created_directory_stacks[region]["nlb"] = nlb_stack_name
     return directory_stack_name, nlb_stack_name
Пример #2
0
def _create_vpc_stack(request, template, region, cfn_stacks_factory):
    if request.config.getoption("vpc_stack"):
        logging.info("Using stack {0} in region {1}".format(
            request.config.getoption("vpc_stack"), region))
        stack = CfnStack(name=request.config.getoption("vpc_stack"),
                         region=region,
                         template=template.to_json())
    else:
        stack = CfnStack(name="integ-tests-vpc-" + random_alphanumeric(),
                         region=region,
                         template=template.to_json())
        cfn_stacks_factory.create_stack(stack)
    return stack
Пример #3
0
    def _fsx_factory(**kwargs):
        # FSx stack
        fsx_template = Template()
        fsx_template.set_version()
        fsx_template.set_description("Create FSx stack")

        # Create security group. If using an existing file system
        # It must be associated to a security group that allows inbound TCP traffic to port 988
        fsx_sg = ec2.SecurityGroup(
            "FSxSecurityGroup",
            GroupDescription="SecurityGroup for testing existing FSx",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="988",
                    ToPort="988",
                    CidrIp="0.0.0.0/0",
                ),
            ],
            VpcId=vpc_stack.cfn_outputs["VpcId"],
        )

        fsx_filesystem = FileSystem(
            SecurityGroupIds=[Ref(fsx_sg)], SubnetIds=[vpc_stack.cfn_outputs["PublicSubnetId"]], **kwargs
        )
        fsx_template.add_resource(fsx_sg)
        fsx_template.add_resource(fsx_filesystem)
        fsx_stack = CfnStack(
            name=fsx_stack_name,
            region=region,
            template=fsx_template.to_json(),
        )
        cfn_stacks_factory.create_stack(fsx_stack)

        return fsx_stack.cfn_resources[kwargs.get("title")]
def api_with_default_settings(api_infrastructure_s3_uri, public_ecr_image_uri,
                              api_definition_s3_uri, request, region):
    factory = CfnStacksFactory(request.config.getoption("credential"))

    params = []
    if api_definition_s3_uri:
        params.append({
            "ParameterKey": "ApiDefinitionS3Uri",
            "ParameterValue": api_definition_s3_uri
        })
    if public_ecr_image_uri:
        params.append({
            "ParameterKey": "PublicEcrImageUri",
            "ParameterValue": public_ecr_image_uri
        })

    template = (
        api_infrastructure_s3_uri or
        f"s3://{region}-aws-parallelcluster/parallelcluster/{get_installed_parallelcluster_version()}"
        "/api/parallelcluster-api.yaml")
    logging.info(
        f"Creating API Server stack in {region} with template {template}")
    stack = CfnStack(
        name=generate_stack_name("integ-tests-api",
                                 request.config.getoption("stackname_suffix")),
        region=region,
        parameters=params,
        capabilities=["CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"],
        template=template,
    )
    try:
        factory.create_stack(stack)
        yield stack
    finally:
        factory.delete_all_stacks()
def custom_security_group(vpc_stack, region, request, cfn_stacks_factory):
    template = Template()
    template.set_version("2010-09-09")
    template.set_description("custom security group stack for testing additional_sg and vpc_security_group_id")
    security_group = template.add_resource(
        SecurityGroup(
            "SecurityGroupResource",
            GroupDescription="custom security group for testing additional_sg and vpc_security_group_id",
            VpcId=vpc_stack.cfn_outputs["VpcId"],
        )
    )
    template.add_resource(
        SecurityGroupIngress(
            "SecurityGroupIngressResource",
            IpProtocol="-1",
            FromPort=0,
            ToPort=65535,
            SourceSecurityGroupId=Ref(security_group),
            GroupId=Ref(security_group),
        )
    )
    stack = CfnStack(
        name=generate_stack_name("integ-tests-custom-sg", request.config.getoption("stackname_suffix")),
        region=region,
        template=template.to_json(),
    )
    cfn_stacks_factory.create_stack(stack)

    yield stack

    if not request.config.getoption("no_delete"):
        cfn_stacks_factory.delete_stack(stack.name, region)
Пример #6
0
def vpc_stacks(cfn_stacks_factory, request):
    """Create VPC used by integ tests in all configured regions."""
    regions = request.config.getoption("regions")
    vpc_stacks = {}
    for region in regions:
        # defining subnets per region to allow AZs override
        public_subnet = SubnetConfig(
            name="PublicSubnet",
            cidr="10.0.0.0/24",
            map_public_ip_on_launch=True,
            has_nat_gateway=True,
            default_gateway=Gateways.INTERNET_GATEWAY,
            availability_zone=random.choice(
                _AVAILABILITY_ZONE_OVERRIDES.get(region, [None])),
        )
        private_subnet = SubnetConfig(
            name="PrivateSubnet",
            cidr="10.0.1.0/24",
            map_public_ip_on_launch=False,
            has_nat_gateway=False,
            default_gateway=Gateways.NAT_GATEWAY,
            availability_zone=random.choice(
                _AVAILABILITY_ZONE_OVERRIDES.get(region, [None])),
        )
        vpc_config = VPCConfig(subnets=[public_subnet, private_subnet])
        template = VPCTemplateBuilder(vpc_config).build()
        stack = CfnStack(name="integ-tests-vpc-" + random_alphanumeric(),
                         region=region,
                         template=template.to_json())
        cfn_stacks_factory.create_stack(stack)
        vpc_stacks[region] = stack

    return vpc_stacks
Пример #7
0
def vpc_stacks(cfn_stacks_factory, request):
    """Create VPC used by integ tests in all configured regions."""
    public_subnet = SubnetConfig(
        name="PublicSubnet",
        cidr="10.0.0.0/24",
        map_public_ip_on_launch=True,
        has_nat_gateway=True,
        default_gateway=Gateways.INTERNET_GATEWAY,
    )
    private_subnet = SubnetConfig(
        name="PrivateSubnet",
        cidr="10.0.1.0/24",
        map_public_ip_on_launch=False,
        has_nat_gateway=False,
        default_gateway=Gateways.NAT_GATEWAY,
    )
    vpc_config = VPCConfig(subnets=[public_subnet, private_subnet])
    template = VPCTemplateBuilder(vpc_config).build()

    regions = request.config.getoption("regions")
    vpc_stacks = {}
    for region in regions:
        stack = CfnStack(name="integ-tests-vpc-" + random_alphanumeric(),
                         region=region,
                         template=template.to_json())
        cfn_stacks_factory.create_stack(stack)
        vpc_stacks[region] = stack

    return vpc_stacks
Пример #8
0
def _write_file_into_efs(region, vpc_stack, efs_stack, request, key_name,
                         cfn_stacks_factory):
    """Write file stack contains a mount target and a instance to write a empty file with random name into the efs."""
    write_file_template = Template()
    write_file_template.set_version("2010-09-09")
    write_file_template.set_description(
        "Stack to write a file to the existing EFS")
    default_security_group_id = get_default_vpc_security_group(
        vpc_stack.cfn_outputs["VpcId"], region)
    write_file_template.add_resource(
        MountTarget(
            "MountTargetResource",
            FileSystemId=efs_stack.cfn_resources["FileSystemResource"],
            SubnetId=vpc_stack.cfn_outputs["PublicSubnetId"],
            SecurityGroups=[default_security_group_id],
        ))
    random_file_name = random_alphanumeric()
    user_data = (
        """
        #cloud-config
        package_update: true
        package_upgrade: true
        runcmd:
        - yum install -y nfs-utils
        - file_system_id_1=""" +
        efs_stack.cfn_resources["FileSystemResource"] + """
        - efs_mount_point_1=/mnt/efs/fs1
        - mkdir -p "${!efs_mount_point_1}"
        - mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev """
        +
        """"${!file_system_id_1}.efs.${AWS::Region}.${AWS::URLSuffix}:/" "${!efs_mount_point_1}"
        - touch ${!efs_mount_point_1}/""" + random_file_name + """
        - umount ${!efs_mount_point_1}
        - opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource InstanceToWriteEFS --region ${AWS::Region}
        """)
    write_file_template.add_resource(
        Instance(
            "InstanceToWriteEFS",
            CreationPolicy={"ResourceSignal": {
                "Timeout": "PT10M"
            }},
            ImageId=retrieve_latest_ami(region, "alinux2"),
            InstanceType="c5.xlarge",
            SubnetId=vpc_stack.cfn_outputs["PublicSubnetId"],
            UserData=Base64(Sub(user_data)),
            KeyName=key_name,
            DependsOn=["MountTargetResource"],
        ))
    write_file_stack = CfnStack(
        name=generate_stack_name("integ-tests-efs-write-file",
                                 request.config.getoption("stackname_suffix")),
        region=region,
        template=write_file_template.to_json(),
    )
    cfn_stacks_factory.create_stack(write_file_stack)

    cfn_stacks_factory.delete_stack(write_file_stack.name, region)

    return random_file_name
Пример #9
0
def _create_vpc_stack(request, template, region, cfn_stacks_factory):
    try:
        set_credentials(region, request.config.getoption("credential"))
        if request.config.getoption("vpc_stack"):
            logging.info("Using stack {0} in region {1}".format(request.config.getoption("vpc_stack"), region))
            stack = CfnStack(name=request.config.getoption("vpc_stack"), region=region, template=template.to_json())
        else:
            stack = CfnStack(
                name=generate_stack_name("integ-tests-vpc", request.config.getoption("stackname_suffix")),
                region=region,
                template=template.to_json(),
            )
            cfn_stacks_factory.create_stack(stack)

    finally:
        unset_credentials()
    return stack
def _create_nlb_stack(cfn_stacks_factory, request, directory_stack, region,
                      test_resources_dir):
    nlb_stack_template_path = os_lib.path.join(test_resources_dir,
                                               "NLB_SimpleAD.yaml")
    nlb_stack_name = generate_stack_name(
        "integ-tests-MultiUserInfraStackNLB",
        request.config.getoption("stackname_suffix"))
    logging.info("Creating stack %s", nlb_stack_name)
    # TODO: don't hardcode this ARN
    certificate_arn = "arn:aws:acm:us-east-1:447714826191:certificate/a17e8574-0cea-4d4c-8e79-a8ebb60f6f47"
    nlb_stack = None
    with open(nlb_stack_template_path) as nlb_stack_template:
        nlb_stack = CfnStack(
            name=nlb_stack_name,
            region=region,
            template=nlb_stack_template.read(),
            parameters=[
                {
                    "ParameterKey": "LDAPSCertificateARN",
                    "ParameterValue": certificate_arn,
                },
                {
                    "ParameterKey": "VPCId",
                    "ParameterValue": directory_stack.cfn_outputs["VpcId"],
                },
                {
                    "ParameterKey":
                    "SubnetId1",
                    "ParameterValue":
                    directory_stack.cfn_outputs["PrivateSubnetIds"].split(",")
                    [0],
                },
                {
                    "ParameterKey":
                    "SubnetId2",
                    "ParameterValue":
                    directory_stack.cfn_outputs["PrivateSubnetIds"].split(",")
                    [1],
                },
                {
                    "ParameterKey":
                    "SimpleADPriIP",
                    "ParameterValue":
                    directory_stack.cfn_outputs["DirectoryDnsIpAddresses"].
                    split(",")[0],
                },
                {
                    "ParameterKey":
                    "SimpleADSecIP",
                    "ParameterValue":
                    directory_stack.cfn_outputs["DirectoryDnsIpAddresses"].
                    split(",")[1],
                },
            ],
        )
    cfn_stacks_factory.create_stack(nlb_stack)
    logging.info("Creation of NLB stack %s complete", nlb_stack_name)
    return nlb_stack
 def _create_network(region, template_path, parameters):
     file_content = extract_template(template_path)
     stack = CfnStack(
         name=generate_stack_name("integ-tests-networking", request.config.getoption("stackname_suffix")),
         region=region,
         template=file_content,
         parameters=parameters,
     )
     factory.create_stack(stack)
     return stack
 def _store_secret(secret):
     template = Template()
     template.set_version("2010-09-09")
     template.set_description("stack to store a secret string")
     template.add_resource(Secret("Secret", SecretString=secret))
     stack = CfnStack(
         name=secret_stack_name,
         region=region,
         template=template.to_json(),
     )
     cfn_stacks_factory.create_stack(stack)
     return stack.cfn_resources["Secret"]
Пример #13
0
def bastion_instance(vpc_stack, cfn_stacks_factory, request, region, key_name):
    """Class to create bastion instance used to execute commands on cluster in private subnet."""
    bastion_stack_name = utils.generate_stack_name(
        "integ-tests-networking-bastion",
        request.config.getoption("stackname_suffix"))

    bastion_template = Template()
    bastion_template.set_version()
    bastion_template.set_description("Create Networking bastion stack")

    bastion_sg = ec2.SecurityGroup(
        "NetworkingTestBastionSG",
        GroupDescription="SecurityGroup for Bastion",
        SecurityGroupIngress=[
            ec2.SecurityGroupRule(
                IpProtocol="tcp",
                FromPort="22",
                ToPort="22",
                CidrIp="0.0.0.0/0",
            ),
        ],
        VpcId=vpc_stack.cfn_outputs["VpcId"],
    )

    instance = ec2.Instance(
        "NetworkingBastionInstance",
        InstanceType="c5.xlarge",
        ImageId=retrieve_latest_ami(region, "alinux2"),
        KeyName=key_name,
        SecurityGroupIds=[Ref(bastion_sg)],
        SubnetId=vpc_stack.cfn_outputs["PublicSubnetId"],
    )
    bastion_template.add_resource(bastion_sg)
    bastion_template.add_resource(instance)
    bastion_template.add_output(
        Output("BastionIP",
               Value=GetAtt(instance, "PublicIp"),
               Description="The Bastion Public IP"))
    bastion_stack = CfnStack(
        name=bastion_stack_name,
        region=region,
        template=bastion_template.to_json(),
    )
    cfn_stacks_factory.create_stack(bastion_stack)
    bastion_ip = bastion_stack.cfn_outputs.get("BastionIP")
    logging.info(f"Bastion_ip: {bastion_ip}")

    yield f"ec2-user@{bastion_ip}"

    if not request.config.getoption("no_delete"):
        cfn_stacks_factory.delete_stack(bastion_stack_name, region)
Пример #14
0
 def _create_network(region, template_path, parameters):
     file_content = extract_template(template_path)
     stack = CfnStack(
         name="integ-tests-networking-{0}{1}{2}".format(
             random_alphanumeric(),
             "-" if request.config.getoption("stackname_suffix") else "",
             request.config.getoption("stackname_suffix"),
         ),
         region=region,
         template=file_content,
         parameters=parameters,
     )
     factory.create_stack(stack)
     return stack
Пример #15
0
def existing_eip(region, request, cfn_stacks_factory):
    template = Template()
    template.set_version("2010-09-09")
    template.set_description("EIP stack for testing existing EIP")
    template.add_resource(EIP("ElasticIP", Domain="vpc"))
    stack = CfnStack(
        name=generate_stack_name("integ-tests-eip",
                                 request.config.getoption("stackname_suffix")),
        region=region,
        template=template.to_json(),
    )
    cfn_stacks_factory.create_stack(stack)

    yield stack.cfn_resources["ElasticIP"]

    if not request.config.getoption("no_delete"):
        cfn_stacks_factory.delete_stack(stack.name, region)
Пример #16
0
def efs_stack(cfn_stacks_factory, request, region):
    """EFS stack contains a single efs resource."""
    efs_template = Template()
    efs_template.set_version("2010-09-09")
    efs_template.set_description("EFS stack created for testing existing EFS")
    efs_template.add_resource(FileSystem("FileSystemResource"))
    stack = CfnStack(
        name=generate_stack_name("integ-tests-efs",
                                 request.config.getoption("stackname_suffix")),
        region=region,
        template=efs_template.to_json(),
    )
    cfn_stacks_factory.create_stack(stack)

    yield stack

    if not request.config.getoption("no_delete"):
        cfn_stacks_factory.delete_stack(stack.name, region)
Пример #17
0
def placement_group_stack(cfn_stacks_factory, request, region):
    """Placement group stack contains a placement group."""
    placement_group_template = Template()
    placement_group_template.set_version()
    placement_group_template.set_description(
        "Placement group stack created for testing existing placement group")
    placement_group_template.add_resource(
        PlacementGroup("PlacementGroup", Strategy="cluster"))
    stack = CfnStack(
        name=generate_stack_name("integ-tests-placement-group",
                                 request.config.getoption("stackname_suffix")),
        region=region,
        template=placement_group_template.to_json(),
    )
    cfn_stacks_factory.create_stack(stack)

    yield stack

    cfn_stacks_factory.delete_stack(stack.name, region)
    def _bastion_factory():
        """Create bastion stack."""
        bastion_template = Template()
        bastion_template.set_version()
        bastion_template.set_description("Create Networking bastion stack")

        bastion_sg = ec2.SecurityGroup(
            "NetworkingTestBastionSG",
            GroupDescription="SecurityGroup for Bastion",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="0.0.0.0/0",
                ),
            ],
            VpcId=vpc_stack.cfn_outputs["VpcId"],
        )

        bastion_instance = ec2.Instance(
            "NetworkingBastionInstance",
            InstanceType="c5.xlarge",
            ImageId=retrieve_latest_ami(region, "alinux2"),
            KeyName=key_name,
            SecurityGroupIds=[Ref(bastion_sg)],
            SubnetId=vpc_stack.cfn_outputs["PublicSubnetId"],
        )
        bastion_template.add_resource(bastion_sg)
        bastion_template.add_resource(bastion_instance)
        bastion_template.add_output(
            Output("BastionIP",
                   Value=GetAtt(bastion_instance, "PublicIp"),
                   Description="The Bastion Public IP"))
        bastion_stack = CfnStack(
            name=bastion_stack_name,
            region=region,
            template=bastion_template.to_json(),
        )
        cfn_stacks_factory.create_stack(bastion_stack)

        return bastion_stack.cfn_outputs.get("BastionIP")
Пример #19
0
 def create_hosted_zone():
     hosted_zone_template = Template()
     hosted_zone_template.set_version("2010-09-09")
     hosted_zone_template.set_description(
         "Hosted zone stack created for testing existing DNS")
     hosted_zone_template.add_resource(
         HostedZone(
             "HostedZoneResource",
             Name=domain_name,
             VPCs=[
                 HostedZoneVPCs(VPCId=vpc_stack.cfn_outputs["VpcId"],
                                VPCRegion=region)
             ],
         ))
     hosted_zone_stack = CfnStack(
         name=hosted_zone_stack_name,
         region=region,
         template=hosted_zone_template.to_json(),
     )
     cfn_stacks_factory.create_stack(hosted_zone_stack)
     return hosted_zone_stack.cfn_resources[
         "HostedZoneResource"], domain_name
Пример #20
0
def enable_vpc_endpoints(vpc_stack, region, cfn_stacks_factory, request):
    prefix = "cn." if region.startswith("cn-") else ""
    # Note that the endpoints service name in China is irregular.
    vpc_endpoints = [
        VPCEndpointConfig(
            name="LogsEndpoint",
            service_name=f"com.amazonaws.{region}.logs",
            type=VPCEndpointConfig.EndpointType.INTERFACE,
            enable_private_dns=True,
        ),
        VPCEndpointConfig(
            name="CFNEndpoint",
            service_name=prefix + f"com.amazonaws.{region}.cloudformation",
            type=VPCEndpointConfig.EndpointType.INTERFACE,
            enable_private_dns=True,
        ),
        VPCEndpointConfig(
            name="EC2Endpoint",
            service_name=prefix + f"com.amazonaws.{region}.ec2",
            type=VPCEndpointConfig.EndpointType.INTERFACE,
            enable_private_dns=True,
        ),
        VPCEndpointConfig(
            name="S3Endpoint",
            service_name=f"com.amazonaws.{region}.s3",
            type=VPCEndpointConfig.EndpointType.GATEWAY,
            enable_private_dns=False,
        ),
        VPCEndpointConfig(
            name="DynamoEndpoint",
            service_name=f"com.amazonaws.{region}.dynamodb",
            type=VPCEndpointConfig.EndpointType.GATEWAY,
            enable_private_dns=False,
        ),
    ]
    vpc_id = vpc_stack.cfn_outputs["VpcId"]
    subnet_id = vpc_stack.cfn_outputs["NoInternetSubnetId"]
    route_table_ids = get_route_tables(subnet_id, region)
    troposphere_template = Template()
    for vpc_endpoint in vpc_endpoints:
        vpc_endpoint_kwargs = {
            "ServiceName": vpc_endpoint.service_name,
            "PrivateDnsEnabled": vpc_endpoint.enable_private_dns,
            "VpcEndpointType": str(vpc_endpoint.type),
            "VpcId": vpc_id,
        }
        if vpc_endpoint.type == VPCEndpointConfig.EndpointType.INTERFACE:
            vpc_endpoint_kwargs["SubnetIds"] = [subnet_id]
        elif vpc_endpoint.type == VPCEndpointConfig.EndpointType.GATEWAY:
            vpc_endpoint_kwargs["RouteTableIds"] = route_table_ids
        troposphere_template.add_resource(
            VPCEndpoint(
                vpc_endpoint.name,
                **vpc_endpoint_kwargs,
            ))
    vpc_endpoints_stack = CfnStack(
        name=generate_stack_name("integ-tests-vpc-endpoints",
                                 request.config.getoption("stackname_suffix")),
        region=region,
        template=troposphere_template.to_json(),
    )

    cfn_stacks_factory.create_stack(vpc_endpoints_stack)
    yield
    if not request.config.getoption("no_delete"):
        cfn_stacks_factory.delete_stack(vpc_endpoints_stack.name, region)
    def _custom_resource(image_id):
        nonlocal stack_name_post_test
        # custom resource stack
        custom_resource_stack_name = generate_stack_name(
            "-".join([image_id, "custom", "resource"]),
            request.config.getoption("stackname_suffix"))
        stack_name_post_test = custom_resource_stack_name
        custom_resource_template = Template()
        custom_resource_template.set_version()
        custom_resource_template.set_description(
            "Create build image custom resource stack")

        # Create a instance role
        managed_policy_arns = [
            "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
            "arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilder",
        ]

        policy_document = iam.Policy(
            PolicyName="myInstanceRoleInlinePolicy",
            PolicyDocument={
                "Statement": [{
                    "Effect":
                    "Allow",
                    "Action": [
                        "ec2:CreateTags",
                        "ec2:ModifyImageAttribute",
                        "s3:GetObject",
                        "cloudformation:ListStacks",
                    ],
                    "Resource":
                    "*",
                }]
            },
        )
        role_name = "".join(["dummyInstanceRole", generate_random_string()])
        instance_role = iam.Role(
            "CustomInstanceRole",
            AssumeRolePolicyDocument={
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": ["ec2.amazonaws.com"]
                    },
                    "Action": ["sts:AssumeRole"]
                }]
            },
            Description="custom instance role for build image test.",
            ManagedPolicyArns=managed_policy_arns,
            Path="/parallelcluster/",
            Policies=[policy_document],
            RoleName=role_name,
        )

        custom_resource_template.add_resource(instance_role)
        custom_resource_stack = CfnStack(
            name=custom_resource_stack_name,
            region=region,
            template=custom_resource_template.to_json(),
            capabilities=["CAPABILITY_NAMED_IAM"],
        )
        cfn_stacks_factory.create_stack(custom_resource_stack)

        instance_role_arn = boto3.client("iam").get_role(
            RoleName=role_name).get("Role").get("Arn")
        logging.info("Custom instance role arn %s", instance_role_arn)

        return instance_role_arn
def _create_directory_stack(
    cfn_stacks_factory,
    request,
    directory_type,
    test_resources_dir,
    ad_admin_password,
    ad_user_password,
    bucket_name,
    region,
    vpc_stack,
):
    directory_stack_name = generate_stack_name(
        f"integ-tests-MultiUserInfraStack{directory_type}",
        request.config.getoption("stackname_suffix"))

    if directory_type not in ("MicrosoftAD", "SimpleAD"):
        raise Exception(f"Unknown directory type: {directory_type}")

    upload_custom_resources(test_resources_dir, bucket_name)
    directory_stack_template_path = os_lib.path.join(test_resources_dir,
                                                     "ad_stack.yaml")
    account_id = (boto3.client(
        "sts", region_name=region, endpoint_url=get_sts_endpoint(
            region)).get_caller_identity().get("Account"))
    config_args = {
        "region": region,
        "account": account_id,
        "admin_node_ami_id": retrieve_latest_ami(region, "alinux2"),
        "admin_node_instance_type": "c5.large",
        "admin_node_key_name": request.config.getoption("key_name"),
        "ad_admin_password": ad_admin_password,
        "ad_user_password": ad_user_password,
        "ad_domain_name": f"{directory_type.lower()}.multiuser.pcluster",
        "default_ec2_domain": "ec2.internal"
        if region == "us-east-1" else f"{region}.compute.internal",
        "ad_admin_user":
        "******" if directory_type == "SimpleAD" else "Admin",
        "num_users_to_create": 100,
        "bucket_name": bucket_name,
        "directory_type": directory_type,
    }
    logging.info("Creating stack %s", directory_stack_name)
    with open(
            render_jinja_template(directory_stack_template_path,
                                  **config_args)) as directory_stack_template:
        params = [
            {
                "ParameterKey": "Vpc",
                "ParameterValue": vpc_stack.cfn_outputs["VpcId"]
            },
            {
                "ParameterKey": "PrivateSubnetOne",
                "ParameterValue": vpc_stack.cfn_outputs["PrivateSubnetId"]
            },
            {
                "ParameterKey":
                "PrivateSubnetTwo",
                "ParameterValue":
                vpc_stack.cfn_outputs["PrivateAdditionalCidrSubnetId"],
            },
            {
                "ParameterKey": "PublicSubnetOne",
                "ParameterValue": vpc_stack.cfn_outputs["PublicSubnetId"]
            },
        ]
        directory_stack = CfnStack(
            name=directory_stack_name,
            region=region,
            template=directory_stack_template.read(),
            parameters=params,
            capabilities=["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"],
        )
    cfn_stacks_factory.create_stack(directory_stack)
    logging.info("Creation of stack %s complete", directory_stack_name)
    return directory_stack