Source code for saltext.azurerm.states.azurerm_keyvault_secret

"""
Azure Resource Manager (ARM) Key Vault Secret State Module

.. versionadded:: 2.1.0

:maintainer: <devops@eitr.tech>
:configuration: This module requires Azure Resource Manager credentials to be passed as a dictionary of
    keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication
    parameters are sensitive, it's recommended to pass them to the states via Pillar.

    Required provider parameters:

    if using username and password:
      * ``subscription_id``
      * ``username``
      * ``password``

    if using a service principal:
      * ``subscription_id``
      * ``tenant``
      * ``client_id``
      * ``secret``

    if using managed identity:
      * ``subscription_id``

    Optional provider parameters:

    **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud.

      Possible values:
        * ``AZURE_PUBLIC_CLOUD`` (default)
        * ``AZURE_CHINA_CLOUD``
        * ``AZURE_US_GOV_CLOUD``
        * ``AZURE_GERMAN_CLOUD``

"""

# Python libs
import logging

import salt.utils.dictdiffer  # pylint: disable=import-error

log = logging.getLogger(__name__)


[docs] def present( name, value, vault_url, content_type=None, enabled=None, expires_on=None, not_before=None, tags=None, version=None, connection_auth=None, **kwargs, ): """ .. versionadded:: 2.1.0 Ensure the specified secret exists within the given key vault. Requires secrets/set permission. Secret properties can be specified as keyword arguments. :param name: The name of the secret. Secret names can only contain alphanumeric characters and dashes. :param value: The value of the secret. :param vault_url: The URL of the vault that the client will access. :param content_type: An arbitrary string indicating the type of the secret. :param enabled: Whether the secret is enabled for use. :param expires_on: When the secret will expire, in UTC. This parameter should be a string representation of a Datetime object in ISO-8601 format. :param not_before: The time before which the secret cannot be used, in UTC. This parameter should be a string representation of a Datetime object in ISO-8601 format. :param tags: A dictionary of strings can be passed as tag metadata to the secret. :param version: The version of the secret. By default, a new version of the secret will not be created if the name is already in use UNLESS the value of the secret is changed. Secret properties will be updated on the latest version unless otherwise specified with this parameter. :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. Example usage: .. code-block:: yaml Ensure secret exists: azurerm_keyvault_secret.present: - name: secretname - value: supersecret - content_type: "text/plain" - vault_url: "https://myvault.vault.azure.net/" - tags: contact_name: Elmer Fudd Gantry """ ret = {"name": name, "result": False, "comment": "", "changes": {}} action = "create" if not isinstance(connection_auth, dict): ret["comment"] = ( "Connection information must be specified via acct or connection_auth dictionary!" ) return ret secret = __salt__["azurerm_keyvault_secret.get_secret"]( name=name, vault_url=vault_url, azurerm_log_level="info", **connection_auth, ) if "error" not in secret: action = "update" if value != secret.get("value"): ret["changes"]["value"] = { "old": "REDACTED_OLD_VALUE", "new": "REDACTED_NEW_VALUE", } if tags: tag_changes = salt.utils.dictdiffer.deep_diff( secret.get("properties", {}).get("tags", {}) or {}, tags or {} ) if tag_changes: ret["changes"]["tags"] = tag_changes if content_type: if ( content_type.lower() != (secret.get("properties", {}).get("content_type", "") or "").lower() ): ret["changes"]["content_type"] = { "old": secret.get("properties", {}).get("content_type"), "new": content_type, } if enabled is not None: if enabled != secret.get("properties", {}).get("enabled"): ret["changes"]["enabled"] = { "old": secret.get("properties", {}).get("enabled"), "new": enabled, } if expires_on: if expires_on != secret.get("properties", {}).get("expires_on"): ret["changes"]["expires_on"] = { "old": secret.get("properties", {}).get("expires_on"), "new": expires_on, } if not_before: if not_before != secret.get("properties", {}).get("not_before"): ret["changes"]["not_before"] = { "old": secret.get("properties", {}).get("not_before"), "new": not_before, } if not ret["changes"]: ret["result"] = True ret["comment"] = f"Secret {name} is already present." return ret if __opts__["test"]: ret["result"] = None ret["comment"] = f"Secret {name} would be updated." return ret if __opts__["test"]: ret["comment"] = f"Secret {name} would be created." ret["result"] = None return ret secret_kwargs = kwargs.copy() secret_kwargs.update(connection_auth) if action == "create" or (action == "update" and ret["changes"].get("value")): secret = __salt__["azurerm_keyvault_secret.set_secret"]( name=name, value=value, vault_url=vault_url, content_type=content_type, enabled=enabled, expires_on=expires_on, not_before=not_before, tags=tags, **secret_kwargs, ) else: secret = __salt__["azurerm_keyvault_secret.update_secret_properties"]( name=name, vault_url=vault_url, version=version, content_type=content_type, enabled=enabled, expires_on=expires_on, not_before=not_before, tags=tags, **secret_kwargs, ) if action == "create": ret["changes"] = {"old": {}, "new": secret} if ret["changes"]["new"].get("value"): ret["changes"]["new"]["value"] = "REDACTED" if "error" not in secret: ret["result"] = True ret["comment"] = f"Secret {name} has been {action}d." return ret ret["comment"] = ( "Failed to {} Secret {}! ({})".format( # pylint: disable=consider-using-f-string action, name, secret.get("error") ) ) if not ret["result"]: ret["changes"] = {} return ret
[docs] def absent(name, vault_url, purge=False, wait=False, connection_auth=None): """ .. versionadded:: 2.1.0 Ensure the specified secret does not exist within the given key vault. :param name: The name of the secret to delete. :param vault_url: The URL of the vault that the client will access. :param purge: Permanently deletes a deleted secret. Possible only in vaults with soft-delete enabled. Performs an irreversible deletion of the specified secret, without possibility for recovery. The operation is not available if the ``recovery_level`` does not specify 'Purgeable'. :param wait: When this method returns, Key Vault has begun deleting the secret. Deletion may take several seconds in a vault with soft-delete enabled. Setting this parameter to ``True`` enables you to wait for deletion to complete. :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. Example usage: .. code-block:: yaml Ensure secret is absent: azurerm_keyvault_secret.absent: - name: secretname - vault_url: "https://myvault.vault.azure.net/" """ ret = {"name": name, "result": False, "comment": "", "changes": {}} action = "delete" deleted = False if not isinstance(connection_auth, dict): ret["comment"] = ( "Connection information must be specified via acct or connection_auth dictionary!" ) return ret secret = __salt__["azurerm_keyvault_secret.get_secret"]( name=name, vault_url=vault_url, azurerm_log_level="info", **connection_auth, ) if "error" in secret: action = "purge" if purge: secret = __salt__["azurerm_keyvault_secret.get_deleted_secret"]( name=name, vault_url=vault_url, azurerm_log_level="info", **connection_auth, ) if "error" in secret: ret["result"] = True ret["comment"] = f"Secret {name} was not found." return ret if __opts__["test"]: ret["comment"] = f"Secret {name} would be {action}d." ret["result"] = None ret["changes"] = { "old": secret, "new": {}, } return ret if action == "delete": deleted = __salt__["azurerm_keyvault_secret.delete_secret"]( name=name, vault_url=vault_url, wait=wait, **connection_auth ) if purge: action = "purge" deleted = __salt__["azurerm_keyvault_secret.purge_deleted_secret"]( name=name, vault_url=vault_url, **connection_auth ) if deleted: ret["result"] = True ret["comment"] = f"Secret {name} has been {action}d." ret["changes"] = {"old": secret, "new": {}} return ret ret["comment"] = f"Failed to {action} Secret {name}!" return ret