Esempio n. 1
0
def main():
    argument_spec = dict(certificate=dict(),
                         certificate_arn=dict(aliases=['arn']),
                         certificate_chain=dict(),
                         domain_name=dict(aliases=['domain']),
                         name_tag=dict(aliases=['name']),
                         private_key=dict(no_log=True),
                         state=dict(default='present',
                                    choices=['present', 'absent']))
    required_if = [
        ['state', 'present', ['certificate', 'name_tag', 'private_key']],
    ]
    module = AnsibleAWSModule(argument_spec=argument_spec,
                              supports_check_mode=True,
                              required_if=required_if)
    acm = ACMServiceManager(module)

    # Check argument requirements
    if module.params['state'] == 'present':
        if module.params['certificate_arn']:
            module.fail_json(
                msg=
                "Parameter 'certificate_arn' is only valid if parameter 'state' is specified as 'absent'"
            )
    else:  # absent
        # exactly one of these should be specified
        absent_args = ['certificate_arn', 'domain_name', 'name_tag']
        if sum([(module.params[a] is not None) for a in absent_args]) != 1:
            for a in absent_args:
                module.debug("%s is %s" % (a, module.params[a]))
            module.fail_json(
                msg=
                "If 'state' is specified as 'absent' then exactly one of 'name_tag', certificate_arn' or 'domain_name' must be specified"
            )

    if module.params['name_tag']:
        tags = dict(Name=module.params['name_tag'])
    else:
        tags = None

    client = module.client('acm')

    # fetch the list of certificates currently in ACM
    certificates = acm.get_certificates(
        client=client,
        module=module,
        domain_name=module.params['domain_name'],
        arn=module.params['certificate_arn'],
        only_tags=tags)

    module.debug("Found %d corresponding certificates in ACM" %
                 len(certificates))

    if module.params['state'] == 'present':
        if len(certificates) > 1:
            msg = "More than one certificate with Name=%s exists in ACM in this region" % module.params[
                'name_tag']
            module.fail_json(msg=msg, certificates=certificates)
        elif len(certificates) == 1:
            # update the existing certificate
            module.debug("Existing certificate found in ACM")
            old_cert = certificates[0]  # existing cert in ACM
            if ('tags'
                    not in old_cert) or ('Name' not in old_cert['tags']) or (
                        old_cert['tags']['Name'] != module.params['name_tag']):
                # shouldn't happen
                module.fail_json(
                    msg="Internal error, unsure which certificate to update",
                    certificate=old_cert)

            if 'certificate' not in old_cert:
                # shouldn't happen
                module.fail_json(
                    msg=
                    "Internal error, unsure what the existing cert in ACM is",
                    certificate=old_cert)

            # Are the existing certificate in ACM and the local certificate the same?
            same = True
            same &= chain_compare(module, old_cert['certificate'],
                                  module.params['certificate'])
            if module.params['certificate_chain']:
                # Need to test this
                # not sure if Amazon appends the cert itself to the chain when self-signed
                same &= chain_compare(module, old_cert['certificate_chain'],
                                      module.params['certificate_chain'])
            else:
                # When there is no chain with a cert
                # it seems Amazon returns the cert itself as the chain
                same &= chain_compare(module, old_cert['certificate_chain'],
                                      module.params['certificate'])

            if same:
                module.debug(
                    "Existing certificate in ACM is the same, doing nothing")
                domain = acm.get_domain_of_cert(
                    client=client,
                    module=module,
                    arn=old_cert['certificate_arn'])
                module.exit_json(certificate=dict(
                    domain_name=domain, arn=old_cert['certificate_arn']),
                                 changed=False)
            else:
                module.debug(
                    "Existing certificate in ACM is different, overwriting")

                # update cert in ACM
                arn = acm.import_certificate(
                    client,
                    module,
                    certificate=module.params['certificate'],
                    private_key=module.params['private_key'],
                    certificate_chain=module.params['certificate_chain'],
                    arn=old_cert['certificate_arn'],
                    tags=tags)
                domain = acm.get_domain_of_cert(client=client,
                                                module=module,
                                                arn=arn)
                module.exit_json(certificate=dict(domain_name=domain, arn=arn),
                                 changed=True)
        else:  # len(certificates) == 0
            module.debug("No certificate in ACM. Creating new one.")
            arn = acm.import_certificate(
                client=client,
                module=module,
                certificate=module.params['certificate'],
                private_key=module.params['private_key'],
                certificate_chain=module.params['certificate_chain'],
                tags=tags)
            domain = acm.get_domain_of_cert(client=client,
                                            module=module,
                                            arn=arn)

            module.exit_json(certificate=dict(domain_name=domain, arn=arn),
                             changed=True)

    else:  # state == absent
        for cert in certificates:
            acm.delete_certificate(client, module, cert['certificate_arn'])
        module.exit_json(
            arns=[cert['certificate_arn'] for cert in certificates],
            changed=(len(certificates) > 0))
Esempio n. 2
0
def main():
    argument_spec = dict(
        certificate=dict(),
        certificate_arn=dict(aliases=['arn']),
        certificate_chain=dict(),
        domain_name=dict(aliases=['domain']),
        name_tag=dict(aliases=['name']),
        private_key=dict(no_log=True),
        tags=dict(type='dict'),
        purge_tags=dict(type='bool', default=False),
        state=dict(default='present', choices=['present', 'absent']),
    )
    module = AnsibleAWSModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )
    acm = ACMServiceManager(module)

    # Check argument requirements
    if module.params['state'] == 'present':
        # at least one of these should be specified.
        absent_args = ['certificate_arn', 'domain_name', 'name_tag']
        if sum([(module.params[a] is not None) for a in absent_args]) < 1:
            for a in absent_args:
                module.debug("%s is %s" % (a, module.params[a]))
            module.fail_json(
                msg=
                "If 'state' is specified as 'present' then at least one of 'name_tag', 'certificate_arn' or 'domain_name' must be specified"
            )
    else:  # absent
        # exactly one of these should be specified
        absent_args = ['certificate_arn', 'domain_name', 'name_tag']
        if sum([(module.params[a] is not None) for a in absent_args]) != 1:
            for a in absent_args:
                module.debug("%s is %s" % (a, module.params[a]))
            module.fail_json(
                msg=
                "If 'state' is specified as 'absent' then exactly one of 'name_tag', 'certificate_arn' or 'domain_name' must be specified"
            )

    filter_tags = None
    desired_tags = None
    if module.params.get('tags') is not None:
        desired_tags = module.params['tags']
    if module.params.get('name_tag') is not None:
        # The module was originally implemented to filter certificates based on the 'Name' tag.
        # Other tags are not used to filter certificates.
        # It would make sense to replace the existing name_tag, domain, certificate_arn attributes
        # with a 'filter' attribute, but that would break backwards-compatibility.
        filter_tags = dict(Name=module.params['name_tag'])
        if desired_tags is not None:
            if 'Name' in desired_tags:
                if desired_tags['Name'] != module.params['name_tag']:
                    module.fail_json(
                        msg=
                        "Value of 'name_tag' conflicts with value of 'tags.Name'"
                    )
            else:
                desired_tags['Name'] = module.params['name_tag']
        else:
            desired_tags = deepcopy(filter_tags)

    client = module.client('acm')

    # fetch the list of certificates currently in ACM
    certificates = acm.get_certificates(
        client=client,
        module=module,
        domain_name=module.params['domain_name'],
        arn=module.params['certificate_arn'],
        only_tags=filter_tags,
    )

    module.debug("Found %d corresponding certificates in ACM" %
                 len(certificates))
    if module.params['state'] == 'present':
        ensure_certificates_present(client, module, acm, certificates,
                                    desired_tags, filter_tags)

    else:  # state == absent
        ensure_certificates_absent(client, module, acm, certificates)