Exemple #1
0
def test_consistency():
    pairs = [
        (MASTER, CLUSTER),
        (CLUSTER, SCHEDULER),
        (CLUSTER, WEBSERVER),
        (CLUSTER, WORKERSET),
    ]
    for (t_outer, t_inner) in pairs:
        for param1, specs1 in t_outer["Parameters"].items():
            for param2, specs2 in t_inner["Parameters"].items():
                if param1 == param2:
                    assert (param1, dump_yaml(specs1)) == (param2,
                                                           dump_yaml(specs2))
def test_dump_yaml():
    """
    YAML dumping needs to use quoted style for strings with newlines,
    use a standard indenting style, and preserve order
    """

    source = ODict((
        (
            "z",
            "short string",
        ),
        (
            "m",
            {
                "Ref": "embedded string"
            },
        ),
        (
            "a",
            "A\nmulti-line\nstring",
        ),
    ))

    actual = dump_yaml(source)

    assert actual == """z: short string
 def test_should_return_security_group_with_egress_cidr_rule(self):
     self.__given_a_session()
     self.__given_a_security_group_with_egress_cidr_rule()
     self.__when_a_security_group_is_created_to_use_cidr()
     result = yaml.load(dump_yaml(load_yaml(self.template.to_yaml())),
                        Loader=yaml.FullLoader)
     self.assertEqual(
         result['Resources']['TestRule']['Properties']['CidrIp'], self.cidr)
 def test_should_return_security_group_with_egress_sg_name_rule(self):
     self.__given_a_session()
     self.__given_a_security_group_with_egress_sg_name_rule()
     self.__when_a_security_group_is_created_to_use_sg_name()
     result = yaml.load(dump_yaml(load_yaml(self.template.to_yaml())),
                        Loader=yaml.FullLoader)
     self.assertEqual(
         result['Resources']['TestRule']['Properties']
         ['DestinationSecurityGroupId']['Ref'], self.sg_name)
    def generate(self, template_path):
        with open(template_path, 'r') as template:
            cfn_yaml = load_yaml(template.read())

            parameter_groups = cfn_yaml['Metadata'][
                'AWS::CloudFormation::Interface']['ParameterGroups']
            parameter_labels = cfn_yaml['Metadata'][
                'AWS::CloudFormation::Interface']['ParameterLabels']
            parameters = cfn_yaml['Parameters']

            print(
                dump_yaml({
                    "ParameterGroups": parameter_groups,
                    "ParameterLabels": parameter_labels,
                    "Parameters": parameters
                }))
def list_resources():
    click.echo("# Framework resources")

    click.echo("## SSM Parameters used")
    click.echo(f"- {constants.CONFIG_PARAM_NAME}")
    click.echo(f"- {constants.CONFIG_PARAM_NAME_ORG_IAM_ROLE_ARN}")

    for file in Path(__file__).parent.resolve().glob("*.template.yaml"):
        if 'empty.template.yaml' == file.name:
            continue
        template_contents = Template(open(file, 'r').read()).render()
        template = cfn_tools.load_yaml(template_contents)
        click.echo(f"## Resources for stack: {file.name.split('.')[0]}")
        table_data = [
            [
                'Logical Name',
                'Resource Type',
                'Name',
            ],
        ]
        table = terminaltables.AsciiTable(table_data)
        for logical_name, resource in template.get('Resources').items():
            resource_type = resource.get('Type')
            name = '-'
            type_to_name = {
                'AWS::IAM::Role': 'RoleName',
                'AWS::SSM::Parameter': 'Name',
                'AWS::S3::Bucket': 'BucketName',
                'AWS::CodePipeline::Pipeline': 'Name',
                'AWS::CodeBuild::Project': 'Name',
                'AWS::CodeCommit::Repository': 'RepositoryName',
                'AWS::SNS::Topic': 'TopicName',
                'AWS::SQS::Queue': 'QueueName',
            }

            if type_to_name.get(resource_type) is not None:
                name = resource.get('Properties',
                                    {}).get(type_to_name.get(resource_type),
                                            'Not Specified')
                if not isinstance(name, str):
                    name = cfn_tools.dump_yaml(name)

            table_data.append([logical_name, resource_type, name])

        click.echo(table.table)
    click.echo(
        f"n.b. AWS::StackName evaluates to {constants.BOOTSTRAP_STACK_NAME}")
    def from_yaml(cls,
                  template_path: Union[str, Path],
                  imports: Optional[Dict[str, str]] = None) -> Template:
        """Loads a Cloudformation template from file.

        Args:
            template_path (Union[str, Path]): The path to the template.
            imports (Optional[Dict[str, str]], optional): Values this template plans
            to import from other stacks exports. Defaults to None.

        Returns:
            Template: A Template object ready for testing.
        """

        with open(template_path) as f:
            raw = f.read()

        tmp_yaml = load_yaml(raw)

        tmp_str = dump_yaml(tmp_yaml)

        template = yaml.load(tmp_str, Loader=yaml.FullLoader)

        return cls(template, imports)
    def run(self):
        stack = self.ensure_stack_is_in_complete_status()
        status = stack.get("StackStatus")

        with self.spoke_regional_client("cloudformation") as cloudformation:
            if status == "ROLLBACK_COMPLETE":
                if self.should_delete_rollback_complete_stacks:
                    cloudformation.ensure_deleted(
                        StackName=self.stack_name_to_use)
                else:
                    raise Exception(
                        f"Stack: {self.stack_name_to_use} is in ROLLBACK_COMPLETE and need remediation"
                    )

        task_output = dict(
            **self.params_for_results_display(),
            account_parameters=tasks.unwrap(self.account_parameters),
            launch_parameters=tasks.unwrap(self.launch_parameters),
            manifest_parameters=tasks.unwrap(self.manifest_parameters),
        )

        all_params = self.get_parameter_values()

        template_to_provision_source = self.input().get("template").open(
            "r").read()
        try:
            template_to_provision = cfn_tools.load_yaml(
                template_to_provision_source)
        except Exception:
            try:
                template_to_provision = cfn_tools.load_json(
                    template_to_provision_source)
            except Exception:
                raise Exception("Could not parse new template as YAML or JSON")

        params_to_use = dict()
        for param_name, p in template_to_provision.get("Parameters",
                                                       {}).items():
            if all_params.get(param_name, p.get("DefaultValue")) is not None:
                params_to_use[param_name] = all_params.get(
                    param_name, p.get("DefaultValue"))

        existing_stack_params_dict = dict()
        existing_template = ""
        if status in [
                "CREATE_COMPLETE",
                "UPDATE_ROLLBACK_COMPLETE",
                "UPDATE_COMPLETE",
                "IMPORT_COMPLETE",
                "IMPORT_ROLLBACK_COMPLETE",
        ]:
            with self.spoke_regional_client(
                    "cloudformation") as cloudformation:
                existing_stack_params_dict = {}
                summary_response = cloudformation.get_template_summary(
                    StackName=self.stack_name_to_use, )
                for parameter in summary_response.get("Parameters"):
                    existing_stack_params_dict[parameter.get(
                        "ParameterKey")] = parameter.get("DefaultValue")
                for stack_param in stack.get("Parameters", []):
                    existing_stack_params_dict[stack_param.get(
                        "ParameterKey")] = stack_param.get("ParameterValue")
                template_body = cloudformation.get_template(
                    StackName=self.stack_name_to_use,
                    TemplateStage="Original").get("TemplateBody")
                try:
                    existing_template = cfn_tools.load_yaml(template_body)
                except Exception:
                    try:
                        existing_template = cfn_tools.load_json(template_body)
                    except Exception:
                        raise Exception(
                            "Could not parse existing template as YAML or JSON"
                        )

        template_to_use = cfn_tools.dump_yaml(template_to_provision)
        if status == "UPDATE_ROLLBACK_COMPLETE":
            need_to_provision = True
        else:
            if existing_stack_params_dict == params_to_use:
                self.info(f"params unchanged")
                if template_to_use == cfn_tools.dump_yaml(existing_template):
                    self.info(f"template the same")
                    need_to_provision = False
                else:
                    self.info(f"template changed")
                    need_to_provision = True
            else:
                self.info(f"params changed")
                need_to_provision = True

        if need_to_provision:
            provisioning_parameters = []
            for p in params_to_use.keys():
                provisioning_parameters.append({
                    "ParameterKey":
                    p,
                    "ParameterValue":
                    params_to_use.get(p)
                })
            with self.spoke_regional_client(
                    "cloudformation") as cloudformation:
                a = dict(
                    StackName=self.stack_name_to_use,
                    TemplateBody=template_to_use,
                    ShouldUseChangeSets=False,
                    Capabilities=self.capabilities,
                    Parameters=provisioning_parameters,
                    ShouldDeleteRollbackComplete=self.
                    should_delete_rollback_complete_stacks,
                )
                if self.use_service_role:
                    a["RoleARN"] = config.get_puppet_stack_role_arn(
                        self.account_id)
                cloudformation.create_or_update(**a)

        task_output["provisioned"] = need_to_provision
        self.info(f"self.execution is {self.execution}")
        if self.execution == constants.EXECUTION_MODE_HUB:
            self.info(
                f"Running in execution mode: {self.execution}, checking for SSM outputs"
            )
            if len(self.ssm_param_outputs) > 0:
                with self.spoke_regional_client(
                        "cloudformation") as spoke_cloudformation:
                    stack_details = aws.get_stack_output_for(
                        spoke_cloudformation,
                        self.stack_name_to_use,
                    )

                for ssm_param_output in self.ssm_param_outputs:
                    self.info(
                        f"writing SSM Param: {ssm_param_output.get('stack_output')}"
                    )
                    with self.hub_client("ssm") as ssm:
                        found_match = False
                        # TODO push into another task
                        for output in stack_details.get("Outputs", []):
                            if output.get("OutputKey") == ssm_param_output.get(
                                    "stack_output"):
                                ssm_parameter_name = ssm_param_output.get(
                                    "param_name")
                                ssm_parameter_name = ssm_parameter_name.replace(
                                    "${AWS::Region}", self.region)
                                ssm_parameter_name = ssm_parameter_name.replace(
                                    "${AWS::AccountId}", self.account_id)
                                found_match = True
                                ssm.put_parameter_and_wait(
                                    Name=ssm_parameter_name,
                                    Value=output.get("OutputValue"),
                                    Type=ssm_param_output.get(
                                        "param_type", "String"),
                                    Overwrite=True,
                                )
                        if not found_match:
                            raise Exception(
                                f"[{self.uid}] Could not find match for {ssm_param_output.get('stack_output')}"
                            )

            self.write_output(task_output)
        else:
            self.write_output(task_output)
Exemple #9
0
sourceName = str(sys.argv[1])
addonName = str(sys.argv[2])
outputName = sourceName
source = open(sourceName, 'r').read()
addon = open(addonName, 'r').read()
addonObj = load_yaml(addon)
sourceObj = load_yaml(source)
sourceKeys = sourceObj.keys()
res = sourceObj['Resources']
if ('TeamAdminPermissionBoundaryPolicy' in res):
    temp = res['TeamAdminPermissionBoundaryPolicy']['Properties'][
        'PolicyDocument']['Statement']
    temp.append(addonObj)
    sourceObj['Resources']['TeamAdminPermissionBoundaryPolicy']['Properties'][
        'PolicyDocument']['Statement'] = temp
if ('TeamWidePermissionBoundaryPolicy' in res):
    temp = res['TeamWidePermissionBoundaryPolicy']['Properties'][
        'PolicyDocument']['Statement']
    temp.append(addonObj)
    sourceObj['Resources']['TeamWidePermissionBoundaryPolicy']['Properties'][
        'PolicyDocument']['Statement'] = temp
'''sourceObj.update(addonObj)
sourceObj.move_to_end('Outputs', last=True)
print(sourceObj)'''

output = dump_yaml(sourceObj)
outputFile = open(outputName, "w")
outputFile.write(output)
outputFile.close()
Exemple #10
0
    def run(self):
        status = self.get_current_status()

        if status == "-":
            self.write_result(
                "-",
                self.version_id,
                effect=constants.CHANGE,
                current_status="-",
                active="N/A",
                notes="Stack would be created",
            )
        elif status == "ROLLBACK_COMPLETE":
            if self.should_delete_rollback_complete_stacks:
                self.write_result(
                    "-",
                    self.version_id,
                    effect=constants.CHANGE,
                    current_status="-",
                    active="N/A",
                    notes="Stack would be replaced",
                )
            else:
                self.write_result(
                    "-",
                    "-",
                    effect=constants.NO_CHANGE,
                    current_status="-",
                    active="N/A",
                    notes="Stack needs remediation - it's in ROLLBACK_COMPLETE",
                )
        else:
            task_output = dict(
                **self.params_for_results_display(),
                account_parameters=tasks.unwrap(self.account_parameters),
                launch_parameters=tasks.unwrap(self.launch_parameters),
                manifest_parameters=tasks.unwrap(self.manifest_parameters),
            )

            all_params = self.get_parameter_values()

            template_to_provision_source = self.input().get("template").open(
                "r").read()
            try:
                template_to_provision = cfn_tools.load_yaml(
                    template_to_provision_source)
            except Exception:
                try:
                    template_to_provision = cfn_tools.load_json(
                        template_to_provision_source)
                except Exception:
                    raise Exception(
                        "Could not parse new template as YAML or JSON")

            params_to_use = dict()
            for param_name, p in template_to_provision.get("Parameters",
                                                           {}).items():
                if all_params.get(param_name,
                                  p.get("DefaultValue")) is not None:
                    params_to_use[param_name] = all_params.get(
                        param_name, p.get("DefaultValue"))

            existing_stack_params_dict = dict()
            existing_template = ""
            if status in [
                    "CREATE_COMPLETE",
                    "UPDATE_ROLLBACK_COMPLETE",
                    "UPDATE_COMPLETE",
                    "IMPORT_COMPLETE",
                    "IMPORT_ROLLBACK_COMPLETE",
            ]:
                with self.spoke_regional_client(
                        "cloudformation") as cloudformation:
                    existing_stack_params_dict = {}
                    stack = cloudformation.describe_stacks(
                        StackName=self.stack_name).get("Stacks")[0]
                    summary_response = cloudformation.get_template_summary(
                        StackName=self.stack_name, )
                    for parameter in summary_response.get("Parameters"):
                        existing_stack_params_dict[parameter.get(
                            "ParameterKey")] = parameter.get("DefaultValue")
                    for stack_param in stack.get("Parameters", []):
                        existing_stack_params_dict[stack_param.get(
                            "ParameterKey")] = stack_param.get(
                                "ParameterValue")
                    template_body = cloudformation.get_template(
                        StackName=self.stack_name,
                        TemplateStage="Original").get("TemplateBody")
                    try:
                        existing_template = cfn_tools.load_yaml(template_body)
                    except Exception:
                        try:
                            existing_template = cfn_tools.load_json(
                                template_body)
                        except Exception:
                            raise Exception(
                                "Could not parse existing template as YAML or JSON"
                            )

            template_to_use = cfn_tools.dump_yaml(template_to_provision)
            if status == "UPDATE_ROLLBACK_COMPLETE":
                self.write_result(
                    "?",
                    self.version_id,
                    effect=constants.CHANGE,
                    current_status=status,
                    active="N/A",
                    notes="Stack would be updated",
                )
            else:
                if existing_stack_params_dict == params_to_use:
                    self.info(f"params unchanged")
                    if template_to_use == cfn_tools.dump_yaml(
                            existing_template):
                        self.info(f"template the same")
                        self.write_result(
                            "?",
                            self.version_id,
                            effect=constants.NO_CHANGE,
                            current_status=status,
                            active="N/A",
                            notes="No change",
                        )
                    else:
                        self.info(f"template changed")
                        self.write_result(
                            "?",
                            self.version_id,
                            effect=constants.CHANGE,
                            current_status=status,
                            active="N/A",
                            notes="Template has changed",
                        )
                else:
                    self.info(f"params changed")
                    self.write_result(
                        "?",
                        self.version_id,
                        effect=constants.CHANGE,
                        current_status=status,
                        active="N/A",
                        notes="Parameters have changed",
                    )
    def test_run(self):
        # setup
        mocked_output = MagicMock()
        self.sut.output = mocked_output

        # exercise
        self.sut.run()

        # verify
        template = load_yaml(
            mocked_output().open().__enter__().write.mock_calls[0][1][0])
        found = 0
        statements = (template.get("Resources").get("TopicPolicies").get(
            "Properties").get("PolicyDocument").get("Statement", []))
        for statement in statements:
            if statement.get("Sid") == "ShareFor01234567890":
                found += 1
                self.assertEqual(
                    "Fn::Sub: arn:${AWS::Partition}:iam::01234567890:root",
                    dump_yaml(statement.get("Principal").get("AWS")).strip(),
                )

            if statement.get("Sid") == "OrganizationalShareForou-0932u0jsdj":
                found += 1
                self.assertEqual(
                    "ou-0932u0jsdj",
                    statement.get("Condition").get("StringEquals").get(
                        "aws:PrincipalOrgID"),
                )

        statements = (template.get("Resources").get("BucketPolicies").get(
            "Properties").get("PolicyDocument").get("Statement", []))
        for statement in statements:
            if statement.get("Sid") == "ShareFor01234567890":
                found += 1
                self.assertEqual(
                    "Fn::Sub: arn:${AWS::Partition}:iam::01234567890:root",
                    dump_yaml(statement.get("Principal").get("AWS")).strip(),
                )

            if statement.get("Sid") == "OrganizationalShareForou-0932u0jsdj":
                found += 1
                self.assertEqual(
                    "ou-0932u0jsdj",
                    statement.get("Condition").get("StringEquals").get(
                        "aws:PrincipalOrgID"),
                )

        self.assertDictEqual(
            dict(
                Type="AWS::Events::EventBusPolicy",
                Condition="RunningInHomeRegion",
                Properties=dict(
                    EventBusName="servicecatalog-puppet-event-bus",
                    Action="events:PutEvents",
                    Principal="01234567890",
                    StatementId="AllowSpokesAccounts01234567890",
                ),
            ),
            template.get("Resources").get(f"EventBusPolicy01234567890"),
        )

        self.assertDictEqual(
            dict(
                Type="AWS::Events::EventBusPolicy",
                Condition="RunningInHomeRegion",
                Properties=dict(
                    EventBusName="servicecatalog-puppet-event-bus",
                    Action="events:PutEvents",
                    Principal="*",
                    StatementId="AllowSpokesOrgsou-0932u0jsdj",
                    Condition=dict(
                        Type="StringEquals",
                        Key="aws:PrincipalOrgID",
                        Value="ou-0932u0jsdj",
                    ),
                ),
            ),
            template.get("Resources").get(f"EventBusPolicyou0932u0jsdj"),
        )

        self.assertEqual(4, found)
Exemple #12
0
def save_template(template_yaml, save_path):
    file = open(save_path, "w+")
    file.write(dump_yaml(template_yaml))
    file.close()
#!/usr/bin/env python

"""Script to convert AWS SAM templates to AWS CloudFormation templates.

Expects SAM template on stdin and prints out CloudFormation template on stdout.
"""

import sys

import boto3
import yaml
from cfn_tools import dump_yaml
from samtranslator.public.translator import ManagedPolicyLoader
from samtranslator.translator.transform import transform

input_fragment = yaml.load(sys.stdin.read())
iam_client = boto3.client('iam')
transformed = transform(input_fragment, {}, ManagedPolicyLoader(iam_client))
print(dump_yaml(transformed))
print("Transforming Template: ", sys.argv[1])
print("Bucket Name: ", sys.argv[2])
print("Bucket Prefix: ", sys.argv[3])

function_names = []

with open(sys.argv[1]) as file:
    text = file.read()
    data = load_yaml(text)

    resources = get_resources(data)

    for resource in resources.items():
        for prop in resource:
            if isinstance(prop, str):  # Logical resource names get skipped
                continue
            print(prop)
            if prop['Type'] == 'Custom::ContactFlow':
                uri = prop['Properties']['ContactFlowUri']

                new_uri_object = process_contact_flow(uri)
                prop['Properties']['ContactFlowPath'] = new_uri_object[
                    'file_path']
                prop['Properties']['BuildNumber'] = sys.argv[3]
                prop['Properties']['ContactFlowBucket'] = new_uri_object[
                    'bucket']

new_file = open(sys.argv[1], "w")
new_file.write(dump_yaml(data))
new_file.close()