# Buggy code
def certificate_managed(
    name, days_remaining=90, managed_private_key=None, append_certs=None, **kwargs
):
    """
    Manage a Certificate

    name
        Path to the certificate

    days_remaining : 90
        The minimum number of days remaining when the certificate should be
        recreated. A value of 0 disables automatic renewal.

    managed_private_key
        Manages the private key corresponding to the certificate. All of the
        arguments supported by :py:func:`x509.private_key_managed
        <salt.states.x509.private_key_managed>` are supported. If `name` is not
        specified or is the same as the name of the certificate, the private
        key and certificate will be written together in the same file.

    append_certs:
        A list of certificates to be appended to the managed file.

    kwargs:
        Any arguments supported by :py:func:`x509.create_certificate
        <salt.modules.x509.create_certificate>` or :py:func:`file.managed
        <salt.states.file.managed>` are supported.

    Examples:

    .. code-block:: yaml

        /etc/pki/ca.crt:
          x509.certificate_managed:
            - signing_private_key: /etc/pki/ca.key
            - CN: ca.example.com
            - C: US
            - ST: Utah
            - L: Salt Lake City
            - basicConstraints: "critical CA:true"
            - keyUsage: "critical cRLSign, keyCertSign"
            - subjectKeyIdentifier: hash
            - authorityKeyIdentifier: keyid,issuer:always
            - days_valid: 3650
            - days_remaining: 0
            - backup: True


    .. code-block:: yaml

        /etc/ssl/www.crt:
          x509.certificate_managed:
            - ca_server: pki
            - signing_policy: www
            - public_key: /etc/ssl/www.key
            - CN: www.example.com
            - days_valid: 90
            - days_remaining: 30
            - backup: True

    """
    if "path" in kwargs:
        name = kwargs.pop("path")

    file_args, kwargs = _get_file_args(name, **kwargs)

    rotate_private_key = False
    new_private_key = False
    if managed_private_key:
        private_key_args = {
            "name": name,
            "new": False,
            "overwrite": False,
            "bits": 2048,
            "passphrase": None,
            "cipher": "aes_128_cbc",
            "verbose": True,
        }
        private_key_args.update(managed_private_key)
        kwargs["public_key_passphrase"] = private_key_args["passphrase"]

        if private_key_args["new"]:
            rotate_private_key = True
            private_key_args["new"] = False

        if _check_private_key(
            private_key_args["name"],
            bits=private_key_args["bits"],
            passphrase=private_key_args["passphrase"],
            new=private_key_args["new"],
            overwrite=private_key_args["overwrite"],
        ):
            private_key = __salt__["x509.get_pem_entry"](
                private_key_args["name"], pem_type="RSA PRIVATE KEY"
            )
        else:
            new_private_key = True
            private_key = __salt__["x509.create_private_key"](
                text=True,
                bits=private_key_args["bits"],
                passphrase=private_key_args["passphrase"],
                cipher=private_key_args["cipher"],
                verbose=private_key_args["verbose"],
            )

        kwargs["public_key"] = private_key

    current_days_remaining = 0
    current_comp = {}

    if os.path.isfile(name):
        try:
            current = __salt__["x509.read_certificate"](certificate=name)
            current_comp = copy.deepcopy(current)
            if "serial_number" not in kwargs:
                current_comp.pop("Serial Number")
                if "signing_cert" not in kwargs:
                    try:
                        current_comp["X509v3 Extensions"]["authorityKeyIdentifier"] = (
                            re.sub(
                                r"serial:([0-9A-F]{2}:)*[0-9A-F]{2}",
                                "serial:--",
                                current_comp["X509v3 Extensions"][
                                    "authorityKeyIdentifier"
                                ],
                            )
                        )
                    except KeyError:
                        pass
            current_comp.pop("Not Before")
            current_comp.pop("MD5 Finger Print")
            current_comp.pop("SHA1 Finger Print")
            current_comp.pop("SHA-256 Finger Print")
            current_notafter = current_comp.pop("Not After")
            current_days_remaining = (
                datetime.datetime.strptime(current_notafter, "%Y-%m-%d %H:%M:%S")
                - datetime.datetime.now()
            ).days
            if days_remaining == 0:
                days_remaining = current_days_remaining - 1
        except salt.exceptions.SaltInvocationError:
            current = "{0} is not a valid Certificate.".format(name)
    else:
        current = "{0} does not exist.".format(name)

    if "ca_server" in kwargs and "signing_policy" not in kwargs:
        raise salt.exceptions.SaltInvocationError(
            "signing_policy must be specified if ca_server is."
        )

    new = __salt__["x509.create_certificate"](testrun=True, **kwargs)

    if isinstance(new, dict):
        new_comp = copy.deepcopy(new)
        new.pop("Issuer Public Key")
        if "serial_number" not in kwargs:
            new_comp.pop("Serial Number")
            if "signing_cert" not in kwargs:
                try:
                    new_comp["X509v3 Extensions"]["authorityKeyIdentifier"] = re.sub(
                        r"serial:([0-9A-F]{2}:)*[0-9A-F]{2}",
                        "serial:--",
                        new_comp["X509v3 Extensions"]["authorityKeyIdentifier"],
                    )
                except KeyError:
                    pass
        new_comp.pop("Not Before")
        new_comp.pop("Not After")
        new_comp.pop("MD5 Finger Print")
        new_comp.pop("SHA1 Finger Print")
        new_comp.pop("SHA-256 Finger Print")
        new_issuer_public_key = new_comp.pop("Issuer Public Key")
    else:
        new_comp = new

    new_certificate = False
    if (
        current_comp == new_comp
        and current_days_remaining > days_remaining
        and __salt__["x509.verify_signature"](name, new_issuer_public_key)
    ):
        certificate = __salt__["x509.get_pem_entry"](name, pem_type="CERTIFICATE")
    else:
        if rotate_private_key and not new_private_key:
            new_private_key = True
            private_key = __salt__["x509.create_private_key"](
                text=True,
                bits=private_key_args["bits"],
                verbose=private_key_args["verbose"],
            )
            kwargs["public_key"] = private_key
        new_certificate = True
        certificate = __salt__["x509.create_certificate"](text=True, **kwargs)

    file_args["contents"] = ""
    private_ret = {}
    if managed_private_key:
        if private_key_args["name"] == name:
            file_args["contents"] = private_key
        else:
            private_file_args = copy.deepcopy(file_args)
            unique_private_file_args, _ = _get_file_args(**private_key_args)
            private_file_args.update(unique_private_file_args)
            private_file_args["contents"] = private_key
            private_ret = __states__["file.managed"](**private_file_args)
            if not private_ret["result"]:
                return private_ret

    file_args["contents"] += salt.utils.stringutils.to_str(certificate)

    if not append_certs:
        append_certs = []
    for append_cert in append_certs:
        file_args["contents"] += __salt__["x509.get_pem_entry"](
            append_cert, pem_type="CERTIFICATE"
        )

    file_args["show_changes"] = False
    ret = __states__["file.managed"](**file_args)

    if ret["changes"]:
        ret["changes"] = {"Certificate": ret["changes"]}
    else:
        ret["changes"] = {}
    if private_ret and private_ret["changes"]:
        ret["changes"]["Private Key"] = private_ret["changes"]
    if new_private_key:
        ret["changes"]["Private Key"] = "New private key generated"
    if new_certificate:
        ret["changes"]["Certificate"] = {
            "Old": current,
            "New": __salt__["x509.read_certificate"](certificate=certificate),
        }

    return ret


# Traceback (SaltInvocationError)
ID: /etc/nginx/certs/localhost.cert.pem
Function: x509.certificate_managed
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/state.py", line 1745, in call
**cdata['kwargs'])
File "/usr/lib/python2.7/site-packages/salt/loader.py", line 1702, in wrapper
return f(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/states/x509.py", line 473, in certificate_managed
new = __salt__['x509.create_certificate'](testrun=True, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/modules/x509.py", line 1484, in create_certificate
passphrase=kwargs['signing_private_key_passphrase'])
File "/usr/lib/python2.7/site-packages/salt/modules/x509.py", line 679, in get_public_key
text = get_pem_entry(text)
File "/usr/lib/python2.7/site-packages/salt/modules/x509.py", line 472, in get_pem_entry
raise salt.exceptions.SaltInvocationError(errmsg)
SaltInvocationError: PEM text not valid:
/etc/nginx/private/localhost.key.pem
Started: 16:29:53.585609
Duration: 99.44 ms
Changes:

# Fixed code
def certificate_managed(name, days_remaining=90, append_certs=None, **kwargs):
    """
    Manage a Certificate

    name
        Path to the certificate

    days_remaining : 90
        The minimum number of days remaining when the certificate should be
        recreated. A value of 0 disables automatic renewal.

    append_certs:
        A list of certificates to be appended to the managed file.

    kwargs:
        Any arguments supported by :py:func:`x509.create_certificate
        <salt.modules.x509.create_certificate>` or :py:func:`file.managed
        <salt.states.file.managed>` are supported.

    Examples:

    .. code-block:: yaml

        /etc/pki/ca.crt:
          x509.certificate_managed:
            - signing_private_key: /etc/pki/ca.key
            - CN: ca.example.com
            - C: US
            - ST: Utah
            - L: Salt Lake City
            - basicConstraints: "critical CA:true"
            - keyUsage: "critical cRLSign, keyCertSign"
            - subjectKeyIdentifier: hash
            - authorityKeyIdentifier: keyid,issuer:always
            - days_valid: 3650
            - days_remaining: 0
            - backup: True


    .. code-block:: yaml

        /etc/ssl/www.crt:
          x509.certificate_managed:
            - ca_server: pki
            - signing_policy: www
            - public_key: /etc/ssl/www.key
            - CN: www.example.com
            - days_valid: 90
            - days_remaining: 30
            - backup: True

    """
    if "path" in kwargs:
        name = kwargs.pop("path")

    if "ca_server" in kwargs and "signing_policy" not in kwargs:
        raise salt.exceptions.SaltInvocationError(
            "signing_policy must be specified if ca_server is."
        )

    if "public_key" not in kwargs and "signing_private_key" not in kwargs:
        raise salt.exceptions.SaltInvocationError(
            "public_key or signing_private_key must be specified."
        )

    ret = {"name": name, "result": False, "changes": {}, "comment": ""}

    is_valid, invalid_reason, current_cert_info = _certificate_is_valid(
        name, days_remaining, append_certs, **kwargs
    )

    if is_valid:
        ret["result"] = True
        ret["comment"] = "Certificate {0} is valid and up to date".format(name)
        return ret

    if __opts__["test"]:
        ret["result"] = None
        ret["comment"] = "Certificate {0} will be created".format(name)
        ret["changes"]["Status"] = {
            "Old": invalid_reason,
            "New": "Certificate will be valid and up to date",
        }
        return ret

    contents = __salt__["x509.create_certificate"](text=True, **kwargs)
    # Check the module actually returned a cert and not an error message as a string
    try:
        __salt__["x509.read_certificate"](contents)
    except salt.exceptions.SaltInvocationError as e:
        ret["result"] = False
        ret["comment"] = (
            "An error occurred creating the certificate {0}. The result returned from x509.create_certificate is not a valid PEM file:\n{1}".format(
                name, str(e)
            )
        )
        return ret

    if not append_certs:
        append_certs = []
    for append_file in append_certs:
        try:
            append_file_contents = __salt__["x509.get_pem_entry"](
                append_file, pem_type="CERTIFICATE"
            )
            contents += append_file_contents
        except salt.exceptions.SaltInvocationError as e:
            ret["result"] = False
            ret["comment"] = (
                "{0} is not a valid certificate file, cannot append it to the certificate {1}.\nThe error returned by the x509 module was:\n{2}".format(
                    append_file, name, str(e)
                )
            )
            return ret

    file_args, extra_args = _get_file_args(name, **kwargs)
    file_args["contents"] = contents
    file_ret = __states__["file.managed"](**file_args)

    if file_ret["changes"]:
        ret["changes"] = {"File": file_ret["changes"]}

    ret["changes"]["Certificate"] = {
        "Old": current_cert_info,
        "New": __salt__["x509.read_certificate"](certificate=name),
    }
    ret["changes"]["Status"] = {
        "Old": invalid_reason,
        "New": "Certificate is valid and up to date",
    }
    ret["comment"] = "Certificate {0} is valid and up to date".format(name)
    ret["result"] = True

    return ret