Exemplo n.º 1
0
def test_bucketpolicy(
    cfn_client,
    s3_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    bucket_name = f"ls-bucket-{short_uid()}"
    template_rendered = jinja2.Template(load_template_raw("s3_bucketpolicy.yaml")).render(
        bucket_name=bucket_name,
        include_policy=True,
    )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        bucket_policy = s3_client.get_bucket_policy(Bucket=bucket_name)["Policy"]
        assert bucket_policy

        nopolicy_template = jinja2.Template(load_template_raw("s3_bucketpolicy.yaml")).render(
            bucket_name=bucket_name,
            include_policy=False,
        )
        nopolicy_changeset_name = f"change-set-{short_uid()}"
        response = cfn_client.create_change_set(
            StackName=stack_name,
            ChangeSetName=nopolicy_changeset_name,
            TemplateBody=nopolicy_template,
            ChangeSetType="UPDATE",
        )
        change_set_id = response["Id"]
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(
            is_stack_created(stack_id)
        )  # TODO: fix cloudformation update status when using changesets

        with pytest.raises(Exception) as err:
            s3_client.get_bucket_policy(Bucket=bucket_name).get("Policy")

        assert err.value.response["Error"]["Code"] == "NoSuchBucketPolicy"

    finally:
        # pass
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 2
0
def test_bucket_autoname(
    cfn_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"STACK-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=load_template_raw("s3_bucket_autoname.yaml"),
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        descr_response = cfn_client.describe_stacks(StackName=stack_id)
        output = descr_response["Stacks"][0]["Outputs"][0]

        assert output["OutputKey"] == "BucketNameOutput"
        assert stack_name.lower() in output["OutputValue"]

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_sns_topic_fifo_without_suffix_fails(
    cfn_client,
    sns_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    """topic name needs .fifo suffix to be valid"""
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    topic_name = f"topic-{short_uid()}"
    template_rendered = jinja2.Template(load_template_raw("sns_topic_fifo_dedup.yaml")).render(
        sns_topic=topic_name
    )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]
    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        stack = cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
        assert stack.get("StackStatus") == "CREATE_FAILED"  # TODO: might be different on AWS, check
    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_statemachine_definitionsubstitution(
    cfn_client,
    lambda_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
    stepfunctions_client,
    s3_client,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=load_template_raw("stepfunctions_statemachine_substitutions.yaml"),
        ChangeSetType="CREATE",
        Capabilities=["CAPABILITY_IAM"],
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)

        wait_until(is_stack_created(stack_id))

        stack_result = cfn_client.describe_stacks(StackName=stack_id)
        assert stack_result["Stacks"][0]["StackStatus"] == "CREATE_COMPLETE"

        outputs = stack_result["Stacks"][0]["Outputs"]
        assert len(outputs) == 1
        statemachine_arn = outputs[0]["OutputValue"]

        # execute statemachine
        ex_result = stepfunctions_client.start_execution(stateMachineArn=statemachine_arn)

        def _is_executed():
            return (
                stepfunctions_client.describe_execution(executionArn=ex_result["executionArn"])[
                    "status"
                ]
                != "RUNNING"
            )

        wait_until(_is_executed)
        execution_desc = stepfunctions_client.describe_execution(
            executionArn=ex_result["executionArn"]
        )
        assert execution_desc["status"] == "SUCCEEDED"
        # sync execution is currently not supported since botocore adds a "sync-" prefix
        # ex_result = stepfunctions_client.start_sync_execution(stateMachineArn=statemachine_arn)

        assert "hello from statemachine" in execution_desc["output"]

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 5
0
def test_update_lambda_inline_code(cfn_client, lambda_client, is_stack_created,
                                   is_stack_updated, cleanup_stacks):
    stack_name = f"stack-{short_uid()}"
    function_name = f"test-fn-{short_uid()}"

    try:
        template_1 = jinja2.Template(
            load_template_raw("lambda_inline_code.yaml")).render(
                lambda_return_value="hello world",
                arch="x86_64",
                function_name=function_name,
            )
        response = cfn_client.create_stack(StackName=stack_name,
                                           TemplateBody=template_1,
                                           Capabilities=["CAPABILITY_IAM"])
        stack_id = response["StackId"]
        assert stack_id
        wait_until(is_stack_created(stack_id))

        rs = lambda_client.get_function(FunctionName=function_name)
        assert function_name == rs["Configuration"]["FunctionName"]
        assert "x86_64" in rs["Configuration"]["Architectures"]
        result = lambda_client.invoke(FunctionName=function_name)
        result = to_str(result["Payload"].read())
        assert result.strip('" \n') == "hello world"

        template_2 = jinja2.Template(
            load_template_raw("lambda_inline_code.yaml")).render(
                lambda_return_value="hello globe",
                arch="arm64",
                function_name=function_name)
        cfn_client.update_stack(StackName=stack_name,
                                TemplateBody=template_2,
                                Capabilities=["CAPABILITY_IAM"])
        wait_until(is_stack_updated(stack_id))

        rs = lambda_client.get_function(FunctionName=function_name)
        assert function_name == rs["Configuration"]["FunctionName"]
        assert "arm64" in rs["Configuration"]["Architectures"]
        result = lambda_client.invoke(FunctionName=function_name)
        result = to_str(result["Payload"].read())
        assert result.strip('" \n') == "hello globe"
    finally:
        # cleanup
        cleanup_stacks([stack_name])
def test_intrinsic_functions(
    cfn_client,
    s3_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
    intrinsic_fn,
    parameter_1,
    parameter_2,
    expected_bucket_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    bucket_name = f"ls-bucket-{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("cfn_intrinsic_functions.yaml")).render(
            bucket_name=bucket_name,
            intrinsic_fn=intrinsic_fn,
        )
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
        Parameters=[
            {
                "ParameterKey": "Param1",
                "ParameterValue": parameter_1
            },
            {
                "ParameterKey": "Param2",
                "ParameterValue": parameter_2
            },
        ],
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        buckets = s3_client.list_buckets()
        bucket_names = [b["Name"] for b in buckets["Buckets"]]

        assert (bucket_name in bucket_names) == expected_bucket_created

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_resolve_ssm_withversion(
    ssm_client,
    cfn_client,
    is_change_set_created_and_available,
    is_stack_created,
    cleanup_changesets,
    cleanup_stacks,
    create_parameter,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    parameter_key = f"param-key-{short_uid()}"
    parameter_value_v0 = f"param-value-{short_uid()}"
    parameter_value_v1 = f"param-value-{short_uid()}"
    parameter_value_v2 = f"param-value-{short_uid()}"

    create_parameter(Name=parameter_key, Type="String", Value=parameter_value_v0)
    v1 = ssm_client.put_parameter(
        Name=parameter_key, Overwrite=True, Type="String", Value=parameter_value_v1
    )
    ssm_client.put_parameter(
        Name=parameter_key, Overwrite=True, Type="String", Value=parameter_value_v2
    )

    template_rendered = jinja2.Template(load_template_raw("resolve_ssm_withversion.yaml")).render(
        parameter_key=parameter_key, parameter_version=str(v1["Version"])
    )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        describe_result = cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
        assert describe_result["StackStatus"] == "CREATE_COMPLETE"

        topic_name = [
            o["OutputValue"] for o in describe_result["Outputs"] if o["OutputKey"] == "TopicName"
        ][0]
        assert topic_name == parameter_value_v1

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 8
0
def test_logstream(
    cfn_client,
    logs_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=load_template_raw("logs_group_and_stream.yaml"),
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        assert (cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
                ["StackStatus"] == "CREATE_COMPLETE")

        descr_response = cfn_client.describe_stacks(StackName=stack_id)
        outputs = {
            o["OutputKey"]: o["OutputValue"]
            for o in descr_response["Stacks"][0]["Outputs"]
        }
        group_name = outputs["LogGroupNameOutput"]
        stream_name = outputs["LogStreamNameOutput"]
        assert group_name
        assert stream_name

        streams = logs_client.describe_log_streams(
            logGroupName=group_name,
            logStreamNamePrefix=stream_name)["logStreams"]
        assert len(streams) == 1
        assert streams[0]["logStreamName"] == stream_name
        assert re.match(
            r"arn:(aws|aws-cn|aws-iso|aws-iso-b|aws-us-gov):logs:.+:.+:log-group:.+:log-stream:.+",
            streams[0]["arn"],
        )
        assert testutil.response_arn_matches_partition(cfn_client,
                                                       streams[0]["arn"])

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 9
0
def test_url_output(
    cfn_client,
    apigateway_client,
    is_change_set_created_and_available,
    is_stack_created,
    cleanup_changesets,
    cleanup_stacks,
    tmp_http_server,
):
    test_port, invocations, proxy = tmp_http_server
    integration_uri = f"http://localhost:{test_port}/{{proxy}}"
    api_name = f"rest-api-{short_uid()}"
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("apigateway-url-output.yaml")).render(
            api_name=api_name, integration_uri=integration_uri)
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        describe_response = cfn_client.describe_stacks(StackName=stack_id)
        outputs = describe_response["Stacks"][0]["Outputs"]
        assert len(outputs) == 2
        api_id = [
            o["OutputValue"] for o in outputs
            if o["OutputKey"] == "ApiV1IdOutput"
        ][0]
        api_url = [
            o["OutputValue"] for o in outputs
            if o["OutputKey"] == "ApiV1UrlOutput"
        ][0]
        assert api_id
        assert api_url
        assert api_id in api_url

        assert f"https://{api_id}.execute-api.{constants.LOCALHOST_HOSTNAME}:4566" in api_url

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 10
0
def test_eventbus_policy_statement(
    cfn_client,
    events_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    event_bus_name = f"event-bus-{short_uid()}"
    statement_id = f"statement-{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("eventbridge_policy_statement.yaml")).render(
            event_bus_name=event_bus_name, statement_id=statement_id)

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )

    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        assert (cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
                ["StackStatus"] == "CREATE_COMPLETE")

        describe_response = events_client.describe_event_bus(
            Name=event_bus_name)
        policy = json.loads(describe_response["Policy"])
        assert policy["Version"] == "2012-10-17"
        assert len(policy["Statement"]) == 1
        statement = policy["Statement"][0]
        assert statement["Sid"] == statement_id
        assert statement["Action"] == "events:PutEvents"
        assert statement["Principal"] == "*"
        assert statement["Effect"] == "Allow"
        assert event_bus_name in statement["Resource"]

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 11
0
def test_parameter_defaults(
    cfn_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
    is_stack_deleted,
    ssm_client,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    ssm_parameter_value = f"custom-{short_uid()}"
    template_rendered = jinja2.Template(load_template_raw("ssm_parameter_defaultname.yaml")).render(
        ssm_parameter_value=ssm_parameter_value
    )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        stack = cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
        parameter_name = stack["Outputs"][0]["OutputValue"]

        assert "CustomParameter" in parameter_name
        param = ssm_client.get_parameter(Name=parameter_name)
        assert param["Parameter"]["Value"] == ssm_parameter_value

        # make sure parameter is deleted
        cfn_client.delete_stack(StackName=stack_id)
        wait_until(is_stack_deleted(stack_id))
        with pytest.raises(Exception) as ctx:
            ssm_client.get_parameter(Name=parameter_name)
        ctx.match("ParameterNotFound")

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_resolve_secretsmanager(
    secretsmanager_client,
    cfn_client,
    is_change_set_created_and_available,
    is_stack_created,
    create_secret,
    create_parameter,
    cleanup_changesets,
    cleanup_stacks,
    template_name,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    parameter_key = f"param-key-{short_uid()}"
    parameter_value = f"param-value-{short_uid()}"

    create_secret(Name=parameter_key, SecretString=parameter_value)

    template_rendered = jinja2.Template(load_template_raw(template_name)).render(
        parameter_key=parameter_key,
    )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        describe_result = cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
        assert describe_result["StackStatus"] == "CREATE_COMPLETE"

        topic_name = [
            o["OutputValue"] for o in describe_result["Outputs"] if o["OutputKey"] == "TopicName"
        ][0]
        assert topic_name == parameter_value

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_list_stack_resources_for_removed_resource(cfn_client,
                                                   is_stack_created,
                                                   is_change_set_finished):
    event_bus_name = f"bus-{short_uid()}"
    template = jinja2.Template(
        load_template_raw("eventbridge_policy.yaml")).render(
            event_bus_name=event_bus_name)

    stack_name = f"stack-{short_uid()}"

    response = cfn_client.create_stack(StackName=stack_name,
                                       TemplateBody=template)
    stack_id = response["StackId"]
    assert stack_id
    wait_until(is_stack_created(stack_id))

    # get list of stack resources
    resources = cfn_client.list_stack_resources(
        StackName=stack_name)["StackResourceSummaries"]
    resources_before = len(resources)
    assert resources_before == 3
    statuses = set([res["ResourceStatus"] for res in resources])
    assert statuses == {"CREATE_COMPLETE", "UPDATE_COMPLETE"}

    # remove one resource from the template, then update stack (via change set)
    template_dict = yaml.load(template)
    template_dict["Resources"].pop("eventPolicy2")
    template2 = yaml.dump(template_dict)

    response = cfn_client.create_change_set(StackName=stack_name,
                                            ChangeSetName="cs1",
                                            TemplateBody=template2)
    change_set_id = response["Id"]
    cfn_client.execute_change_set(ChangeSetName=change_set_id)
    wait_until(is_change_set_finished(change_set_id))

    # get list of stack resources, again - make sure that deleted resource is not contained in result
    resources = cfn_client.list_stack_resources(
        StackName=stack_name)["StackResourceSummaries"]
    assert len(resources) == resources_before - 1
    statuses = set([res["ResourceStatus"] for res in resources])
    assert statuses == {"CREATE_COMPLETE", "UPDATE_COMPLETE"}
def test_sns_subscription(
    cfn_client,
    sns_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    topic_name = f"topic-{short_uid()}"
    queue_name = f"topic-{short_uid()}"
    template_rendered = jinja2.Template(load_template_raw("sns_topic_subscription.yaml")).render(
        topic_name=topic_name, queue_name=queue_name
    )
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        outputs = cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]["Outputs"]
        assert len(outputs) == 1 and outputs[0]["OutputKey"] == "TopicArnOutput"
        topic_arn = outputs[0]["OutputValue"]
        assert topic_arn is not None

        subscriptions = sns_client.list_subscriptions_by_topic(TopicArn=topic_arn)
        assert len(subscriptions["Subscriptions"]) > 0

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 15
0
def test_kms_key_disabled(
    cfn_client,
    sqs_client,
    kms_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"

    template_rendered = load_template_raw("kms_key_disabled.yaml")
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        outputs = cfn_client.describe_stacks(
            StackName=stack_id)["Stacks"][0]["Outputs"]
        assert len(outputs) == 1
        key_id = outputs[0]["OutputValue"]
        assert key_id
        my_key = kms_client.describe_key(KeyId=key_id)
        assert not my_key["KeyMetadata"]["Enabled"]

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_sns_topic_fifo_with_deduplication(
    cfn_client,
    sns_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    topic_name = f"topic-{short_uid()}.fifo"
    template_rendered = jinja2.Template(load_template_raw("sns_topic_fifo_dedup.yaml")).render(
        sns_topic=topic_name
    )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        topics = sns_client.list_topics()["Topics"]
        topic_arns = [t["TopicArn"] for t in topics]

        assert len([t for t in topic_arns if topic_name in t]) == 1

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 17
0
def test_lambda_autogenerated_name(
    cfn_client,
    lambda_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    lambda_functional_id = f"MyFn{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("cfn_lambda_noname.yaml")).render(
            lambda_functional_id=lambda_functional_id)

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        outputs = cfn_client.describe_stacks(
            StackName=stack_id)["Stacks"][0]["Outputs"]
        assert len(outputs) == 1
        assert lambda_functional_id in outputs[0]["OutputValue"]

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_create_stack_with_ssm_parameters(cfn_client, ssm_client, sns_client,
                                          cleanup_stacks, is_stack_created):
    stack_name = f"stack-{short_uid()}"
    parameter_name = f"ls-param-{short_uid()}"
    parameter_value = f"ls-param-value-{short_uid()}"
    parameter_logical_id = "parameter123"
    ssm_client.put_parameter(Name=parameter_name,
                             Value=parameter_value,
                             Type="String")
    template = load_template_raw("dynamicparameter_ssm_string.yaml")
    template_rendered = jinja2.Template(template).render(
        parameter_name=parameter_name)
    response = cfn_client.create_stack(
        StackName=stack_name,
        TemplateBody=template_rendered,
    )
    stack_id = response["StackId"]
    assert stack_id

    try:
        wait_until(is_stack_created(stack_id))

        created_stack = cfn_client.describe_stacks(
            StackName=stack_name)["Stacks"][0]
        assert created_stack is not None
        assert created_stack["Parameters"][0][
            "ParameterKey"] == parameter_logical_id
        assert created_stack["Parameters"][0][
            "ParameterValue"] == parameter_name
        assert created_stack["Parameters"][0][
            "ResolvedValue"] == parameter_value

        topics = sns_client.list_topics()
        topic_arns = [t["TopicArn"] for t in topics["Topics"]]
        assert any(parameter_value in t for t in topic_arns)
    finally:
        cleanup_stacks([stack_id])
def test_sqs_queue_policy(
    cfn_client,
    sqs_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"

    template_rendered = load_template_raw("sqs_with_queuepolicy.yaml")
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        outputs = cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]["Outputs"]
        assert len(outputs) == 1
        queue_url = outputs[0]["OutputValue"]
        resp = sqs_client.get_queue_attributes(QueueUrl=queue_url, AttributeNames=["Policy"])
        assert (
            "Statement" in resp["Attributes"]["Policy"]
        )  # just kind of a smoke test to see if its set

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_policy_attachments(
    cfn_client,
    iam_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):

    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    role_name = f"role-{short_uid()}"
    group_name = f"group-{short_uid()}"
    user_name = f"user-{short_uid()}"
    policy_name = f"policy-{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("iam_policy_attachments.yaml")).render(
            role_name=role_name,
            policy_name=policy_name,
            user_name=user_name,
            group_name=group_name,
        )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        # check inline policies
        role_inline_policies = iam_client.list_role_policies(
            RoleName=role_name)
        user_inline_policies = iam_client.list_user_policies(
            UserName=user_name)
        group_inline_policies = iam_client.list_group_policies(
            GroupName=group_name)
        assert len(role_inline_policies["PolicyNames"]) == 1
        assert len(user_inline_policies["PolicyNames"]) == 1
        assert len(group_inline_policies["PolicyNames"]) == 1

        # check managed/attached policies
        role_attached_policies = iam_client.list_attached_role_policies(
            RoleName=role_name)
        user_attached_policies = iam_client.list_attached_user_policies(
            UserName=user_name)
        group_attached_policies = iam_client.list_attached_group_policies(
            GroupName=group_name)
        assert len(role_attached_policies["AttachedPolicies"]) == 1
        assert len(user_attached_policies["AttachedPolicies"]) == 1
        assert len(group_attached_policies["AttachedPolicies"]) == 1

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 21
0
def test_event_rule_to_logs(
    cfn_client,
    events_client,
    logs_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    event_rule_name = f"event-rule-{short_uid()}"
    log_group_name = f"log-group-{short_uid()}"
    message_token = f"test-message-{short_uid()}"
    event_bus_name = f"bus-{short_uid()}"
    resource_policy_name = f"policy-{short_uid()}"

    template_rendered = jinja2.Template(
        load_template_raw("events_loggroup.yaml")).render(
            event_rule_name=event_rule_name,
            log_group_name=log_group_name,
            event_bus_name=event_bus_name,
            resource_policy_name=resource_policy_name,
        )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )

    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        assert (cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
                ["StackStatus"] == "CREATE_COMPLETE")

        log_groups = logs_client.describe_log_groups(
            logGroupNamePrefix=log_group_name)["logGroups"]
        log_group_names = [lg["logGroupName"] for lg in log_groups]
        assert log_group_name in log_group_names

        resp = events_client.put_events(
            Entries=[{
                "Source": "unittest",
                "Resources": [],
                "DetailType": "ls-detail-type",
                "Detail": json.dumps({"messagetoken": message_token}),
                "EventBusName": event_bus_name,
            }])
        assert len(resp["Entries"]) == 1
        wait_until(
            lambda: len(
                logs_client.describe_log_streams(logGroupName=log_group_name)[
                    "logStreams"]) > 0,
            1.0,
            5,
            "linear",
        )
        log_streams = logs_client.describe_log_streams(
            logGroupName=log_group_name)["logStreams"]
        assert len(log_streams) == 1

        log_events = logs_client.get_log_events(
            logGroupName=log_group_name,
            logStreamName=log_streams[0]["logStreamName"])
        assert message_token in log_events["events"][0]["message"]

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
Exemplo n.º 22
0
def test_eventbus_policies(
    cfn_client,
    events_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    event_bus_name = f"event-bus-{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("eventbridge_policy.yaml")).render(
            event_bus_name=event_bus_name)

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )

    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))
        assert (cfn_client.describe_stacks(StackName=stack_id)["Stacks"][0]
                ["StackStatus"] == "CREATE_COMPLETE")

        # check that both statements were added
        describe_response = events_client.describe_event_bus(
            Name=event_bus_name)
        policy = json.loads(describe_response["Policy"])
        assert len(policy["Statement"]) == 2

        # verify physical resource ID creation
        pol1_description = cfn_client.describe_stack_resource(
            StackName=stack_id, LogicalResourceId="eventPolicy")
        pol2_description = cfn_client.describe_stack_resource(
            StackName=stack_id, LogicalResourceId="eventPolicy2")
        assert (pol1_description["StackResourceDetail"]["PhysicalResourceId"]
                !=
                pol2_description["StackResourceDetail"]["PhysicalResourceId"])

        # TODO: Fix cloudformation change set update status
        # TODO: Fix second changeset execution (should delete resource in stack's _resource_states)
        # delete one of the 2 statements and check if the other still exists
        # template_rendered_single_policy = jinja2.Template(load_template_raw("eventbridge_policy_singlepolicy.yaml")).render(
        #     event_bus_name=event_bus_name
        # )
        # change_set_name = f"change-set-update-{short_uid()}"
        # response = cfn_client.create_change_set(
        #     StackName=stack_name,
        #     ChangeSetName=change_set_name,
        #     TemplateBody=template_rendered_single_policy,
        # )
        # change_set_id = response["Id"]
        # wait_until(is_change_set_created_and_available(change_set_id))
        # cfn_client.execute_change_set(ChangeSetName=change_set_id)
        # cfn_client.get_waiter("stack_create_complete").wait(StackName=stack_id, WaiterConfig={'Delay': 5, 'MaxAttempts': 10})  # TODO: should be get_waiter("stack_update_complete")
        #
        # describe_response = events_client.describe_event_bus(Name=event_bus_name)
        # policy = json.loads(describe_response['Policy'])
        # assert len(policy['Statement']) == 1

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_nested_statemachine_with_sync2(
    cfn_client,
    lambda_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
    stepfunctions_client,
    s3_client,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=load_template_raw("sfn_nested_sync2.json"),
        ChangeSetType="CREATE",
        Capabilities=["CAPABILITY_IAM"],
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)

        wait_until(is_stack_created(stack_id))

        stack_result = cfn_client.describe_stacks(StackName=stack_id)
        assert stack_result["Stacks"][0]["StackStatus"] == "CREATE_COMPLETE"

        parent_arn = [
            o["OutputValue"]
            for o in stack_result["Stacks"][0]["Outputs"]
            if o["OutputKey"] == "ParentStateMachineArnOutput"
        ][0]

        ex_result = stepfunctions_client.start_execution(
            stateMachineArn=parent_arn, input='{"Value": 1}'
        )

        def _is_executed():
            return (
                stepfunctions_client.describe_execution(executionArn=ex_result["executionArn"])[
                    "status"
                ]
                != "RUNNING"
            )

        wait_until(_is_executed)
        execution_desc = stepfunctions_client.describe_execution(
            executionArn=ex_result["executionArn"]
        )
        assert execution_desc["status"] == "SUCCEEDED"
        output = json.loads(execution_desc["output"])
        assert output["Value"] == 3

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_delete_role_detaches_role_policy(
    cfn_client,
    iam_client,
    cleanup_stacks,
    cleanup_changesets,
    is_change_set_created_and_available,
    is_stack_created,
):
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    role_name = f"LsRole{short_uid()}"
    policy_name = f"LsPolicy{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("iam_role_policy.yaml")).render(
            role_name=role_name,
            policy_name=policy_name,
            include_policy=True,
        )

    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        attached_policies = iam_client.list_attached_role_policies(
            RoleName=role_name)["AttachedPolicies"]
        assert len(attached_policies) > 0

        # nopolicy_template = jinja2.Template(load_template_raw("iam_role_policy.yaml")).render(
        #     role_name=role_name,
        #     policy_name=policy_name,
        #     include_policy=False,
        # )
        # nopolicy_changeset_name = f"change-set-{short_uid()}"
        # response = cfn_client.create_change_set(
        #     StackName=stack_name,
        #     ChangeSetName=nopolicy_changeset_name,
        #     TemplateBody=nopolicy_template,
        #     ChangeSetType="UPDATE",
        # )
        # change_set_id = response["Id"]
        # wait_until(is_change_set_created_and_available(change_set_id))
        # cfn_client.execute_change_set(ChangeSetName=change_set_id)
        # time.sleep(5)
        # wait_until(is_stack_created(stack_id))  # TODO: wrong format
        # wait_until(is_stack_deleted(stack_id))

        # TODO: need to update stack to delete only a single resource
        # attached_policies = iam_client.list_attached_role_policies(RoleName=role_name)['AttachedPolicies']
        # assert len(attached_policies) == 0

    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])
def test_cfn_apigateway_aws_integration(
    cfn_client,
    apigateway_client,
    s3_client,
    iam_client,
    is_change_set_created_and_available,
    is_stack_created,
    cleanup_changesets,
    cleanup_stacks,
):
    api_name = f"rest-api-{short_uid()}"
    stack_name = f"stack-{short_uid()}"
    change_set_name = f"change-set-{short_uid()}"
    template_rendered = jinja2.Template(
        load_template_raw("apigw-awsintegration-request-parameters.yaml")
    ).render(api_name=api_name)
    response = cfn_client.create_change_set(
        StackName=stack_name,
        ChangeSetName=change_set_name,
        TemplateBody=template_rendered,
        ChangeSetType="CREATE",
    )
    change_set_id = response["Id"]
    stack_id = response["StackId"]

    try:
        wait_until(is_change_set_created_and_available(change_set_id))
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        wait_until(is_stack_created(stack_id))

        # check resources creation
        apis = [
            api for api in apigateway_client.get_rest_apis()["items"]
            if api["name"] == api_name
        ]
        assert len(apis) == 1
        api_id = apis[0]["id"]

        # check resources creation
        resources = apigateway_client.get_resources(restApiId=api_id)["items"]
        assert (resources[0]["resourceMethods"]["GET"]["requestParameters"]
                ["method.request.path.id"] is False)
        assert (resources[0]["resourceMethods"]["GET"]["methodIntegration"]
                ["requestParameters"]["integration.request.path.object"] ==
                "method.request.path.id")

        # check domains creation
        domain_names = [
            domain["domainName"]
            for domain in apigateway_client.get_domain_names()["items"]
        ]
        assert len(domain_names) == 1
        assert domain_names[0] == "localstack.cloud"

        # check basepath mappings creation
        mappings = [
            mapping["basePath"]
            for mapping in apigateway_client.get_base_path_mappings(
                domainName=domain_names[0])["items"]
        ]
        assert len(mappings) == 1
        assert mappings[0] == "(none)"
    finally:
        cleanup_changesets([change_set_id])
        cleanup_stacks([stack_id])