Beispiel #1
0
def run_sample():
    # Instantiate a secret client that will be used to call the service.
    # Notice that the client is using default Azure credentials.
    # To make default credentials work, ensure that environment variables 'AZURE_CLIENT_ID',
    # 'AZURE_CLIENT_SECRET' and 'AZURE_TENANT_ID' are set with the service principal credentials.
    VAULT_URL = os.environ["VAULT_URL"]
    credential = DefaultAzureCredential()
    client = SecretClient(vault_url=VAULT_URL, credential=credential)
    try:
        # Let's create secrets holding storage and bank accounts credentials. If the secret
        # already exists in the Key Vault, then a new version of the secret is created.
        print("\n1. Create Secret")
        bank_secret = client.set_secret("recoverPurgeBankSecretName",
                                        "recoverPurgeSecretValue1")
        storage_secret = client.set_secret("recoverPurgeStorageSecretName",
                                           "recoverPurgeSecretValue2")
        print("Secret with name '{0}' was created.".format(bank_secret.name))
        print("Secret with name '{0}' was created.".format(
            storage_secret.name))

        # The storage account was closed, need to delete its credentials from the Key Vault.
        print("\n2. Delete a Secret")
        secret = client.delete_secret(bank_secret.name)
        time.sleep(20)
        print("Secret with name '{0}' was deleted on date {1}.".format(
            secret.name, secret.deleted_date))

        # We accidentally deleted the bank account secret. Let's recover it.
        # A deleted secret can only be recovered if the Key Vault is soft-delete enabled.
        print("\n3. Recover Deleted  Secret")
        recovered_secret = client.recover_deleted_secret(bank_secret.name)
        print("Recovered Secret with name '{0}'.".format(
            recovered_secret.name))

        # Let's delete storage account now.
        # If the keyvault is soft-delete enabled, then for permanent deletion deleted secret needs to be purged.
        client.delete_secret(storage_secret.name)

        # To ensure secret is deleted on the server side.
        print("\nDeleting Storage Secret...")
        time.sleep(20)

        # To ensure permanent deletion, we might need to purge the secret.
        print("\n4. Purge Deleted Secret")
        client.purge_deleted_secret(storage_secret.name)
        print("Secret has been permanently deleted.")

    except HttpResponseError as e:
        if "(NotSupported)" in e.message:
            print(
                "\n{0} Please enable soft delete on Key Vault to perform this operation."
                .format(e.message))
        else:
            print("\nrun_sample has caught an error. {0}".format(e.message))

    finally:
        print("\nrun_sample done")
Beispiel #2
0
class KeyVault():
    def __init__(self, vault_url):
        self.credential = DefaultAzureCredential()
        self.secret_client = SecretClient(vault_url=vault_url,
                                          credential=self.credential)

    def get_secret(self, secret_name):
        secret = self.secret_client.get_secret(secret_name)
        print(secret.enabled)
        return secret.value

    def update_secret(self, secret_name, secret_data):
        secret = self.secret_client.set_secret(secret_name, secret_data)
        return secret.properties.version

    def delete_secret(self, secret_name):
        secret = self.secret_client.begin_delete_secret(secret_name).wait()
        self.secret_client.purge_deleted_secret(secret_name)
        print(secret)
    # We accidentally deleted the bank account secret. Let's recover it.
    # A deleted secret can only be recovered if the Key Vault is soft-delete enabled.
    print("\n.. Recover Deleted  Secret")
    recovered_secret = client.recover_deleted_secret(bank_secret.name)
    print("Recovered Secret with name '{0}'.".format(recovered_secret.name))

    # Let's delete storage account now.
    # If the keyvault is soft-delete enabled, then for permanent deletion deleted secret needs to be purged.
    client.delete_secret(storage_secret.name)

    # To ensure secret is deleted on the server side.
    print("\nDeleting Storage Secret...")
    time.sleep(20)

    # To ensure permanent deletion, we might need to purge the secret.
    print("\n.. Purge Deleted Secret")
    client.purge_deleted_secret(storage_secret.name)
    print("Secret has been permanently deleted.")

except HttpResponseError as e:
    if "(NotSupported)" in e.message:
        print(
            "\n{0} Please enable soft delete on Key Vault to perform this operation."
            .format(e.message))
    else:
        print("\nrun_sample has caught an error. {0}".format(e.message))

finally:
    print("\nrun_sample done")
Beispiel #4
0
    print("Secret with name '{0}' created with value '{1}'".format(
        secret.name, secret.value))

    # Backups are good to have, if in case secrets gets deleted accidentally.
    # For long term storage, it is ideal to write the backup to a file.
    print("\n.. Create a backup for an existing Secret")
    secret_backup = client.backup_secret(secret.name)
    print("Backup created for secret with name '{0}'.".format(secret.name))

    # The storage account secret is no longer in use, so you delete it.
    print("\n.. Deleting secret...")
    delete_operation = client.begin_delete_secret(secret.name)
    deleted_secret = delete_operation.result()
    print("Deleted secret with name '{0}'".format(deleted_secret.name))

    # Wait for the deletion to complete before purging the secret.
    # The purge will take some time, so wait before restoring the backup to avoid a conflict.
    delete_operation.wait()
    print("\n.. Purge the secret")
    client.purge_deleted_secret(deleted_secret.name)
    time.sleep(60)
    print("Purged secret with name '{0}'".format(deleted_secret.name))

    # In the future, if the secret is required again, we can use the backup value to restore it in the Key Vault.
    print("\n.. Restore the secret using the backed up secret bytes")
    secret = client.restore_secret_backup(secret_backup)
    print("Restored secret with name '{0}'".format(secret.name))

except HttpResponseError as e:
    print("\nThis sample has caught an error. {0}".format(e.message))
class AzureKeyVault:
    headers = None
    kvName = None
    token = None
    tracer = None
    uri = None

    def __init__(self,
                 tracer: logging.Logger,
                 kvName: str,
                 msiClientId: Optional[str] = None):
        self.tracer = tracer
        self.tracer.info("initializing KeyVault %s" % kvName)
        self.kvName = kvName
        self.uri = "https://%s.vault.azure.net" % kvName
        self.token = ManagedIdentityCredential(client_id=msiClientId)
        self.kv_client = SecretClient(vault_url=self.uri,
                                      credential=self.token)

    # Set a secret in the KeyVault
    def setSecret(self, secretName: str, secretValue: str) -> bool:
        self.tracer.info("setting KeyVault secret for secretName=%s" %
                         secretName)
        try:
            self.kv_client.set_secret(secretName, secretValue)
        except Exception as e:
            self.tracer.critical("could not set KeyVault secret (%s)" % e)
            sys.exit(ERROR_SETTING_KEYVAULT_SECRET)
        return True

    # Delete a secret from the KeyVault
    def deleteSecret(self, secretName: str) -> bool:
        self.tracer.info("deleting KeyVault secret %s" % secretName)
        try:
            poller = self.kv_client.begin_delete_secret(secretName)
            poller.wait()
            self.kv_client.purge_deleted_secret(secretName)
        except Exception as e:
            self.tracer.critical("could not delete KeyVault secret (%s)" % e)
            return False
        return True

    # Get the current version of a specific secret in the KeyVault
    def getSecret(self,
                  secretId: str,
                  version: Optional[str] = None) -> KeyVaultSecret:
        self.tracer.info("getting KeyVault secret for secretId=%s" % secretId)
        secret = None
        try:
            secret = self.kv_client.get_secret(secretId, version)
        except Exception as e:
            self.tracer.error(
                "could not get KeyVault secret for secretId=%s (%s)" %
                (secretId, e))
        return secret

    # Get the current versions of all secrets inside the customer KeyVault
    def getCurrentSecrets(self) -> Dict[str, str]:
        self.tracer.info("getting current KeyVault secrets")
        secrets = {}
        try:
            kvSecrets = self.kv_client.list_properties_of_secrets()
            for k in kvSecrets:
                secrets[k.name] = self.kv_client.get_secret(k.name).value
        except Exception as e:
            self.tracer.error("could not get current KeyVault secrets (%s)" %
                              e)
        return secrets

    # Check if a KeyVault with a specified name exists
    def exists(self) -> bool:
        self.tracer.info("checking if KeyVault %s exists" % self.kvName)
        try:
            kvSecrets = self.kv_client.list_properties_of_secrets(
                max_page_size=1)
            if kvSecrets:
                self.tracer.info("KeyVault %s exists" % self.kvName)
                return True
        except Exception as e:
            self.tracer.error(
                "could not determine is KeyVault %s exists (%s)" %
                (self.kvName, e))
        self.tracer.info("KeyVault %s does not exist" % self.kvName)
        return False
    def deleted_secret_recovery(self):
        """
        a sample of enumerating, retrieving, recovering and purging deleted secrets from a key vault
        """
        # create a vault enabling the soft delete feature
        vault = self.create_vault()

        # create a secret client
        credential = DefaultAzureCredential()
        secret_client = SecretClient(vault_url=vault.properties.vault_uri,
                                     credential=credential)

        # create secrets in the vault
        secret_to_recover = get_name('secret')
        secret_to_purge = get_name('secret')

        secret = secret_client.set_secret(secret_to_recover,
                                          "secret to restore")
        print('created secret {}'.format(secret.name))

        secret = secret_client.set_secret(secret_to_purge, "secret to purge")
        print('created secret {}'.format(secret.name))

        # list the name of all of the secrets in the client's vault
        secret_properties = secret_client.list_properties_of_secrets()
        print("all of the secrets in the client's vault:")
        for secret_property in secret_properties:
            print(secret_property.name)

        # delete the secrets
        delete_secret_poller = secret_client.begin_delete_secret(
            secret_to_recover)
        deleted_secret = delete_secret_poller.result()
        delete_secret_poller.wait()
        print('deleted secret {}'.format(deleted_secret.name))

        delete_secret_poller = secret_client.begin_delete_secret(
            secret_to_purge)
        deleted_secret = delete_secret_poller.result()
        delete_secret_poller.wait()
        print('deleted secret {}'.format(deleted_secret.name))

        # list the deleted secrets
        deleted_secrets = secret_client.list_deleted_secrets()
        print("all of the deleted secrets in the client's vault:")
        for deleted_secret in deleted_secrets:
            print(deleted_secret.name)

        # recover a deleted secret
        recover_secret_poller = secret_client.begin_recover_deleted_secret(
            secret_to_recover)
        recovered_secret = recover_secret_poller.result()
        print('recovered secret {}'.format(recovered_secret.name))

        # purge a deleted secret
        secret_client.purge_deleted_secret(secret_to_purge)
        time.sleep(50)
        print('purged secret {}'.format(secret_to_purge))

        # list the name of all of the secrets in the client's vault
        secret_properties = secret_client.list_properties_of_secrets()
        print("all of the secrets in the client's vault:")
        for secret_property in secret_properties:
            print(secret_property.name)
Beispiel #7
0
class AzureKeyVault(AzureApi):
    """Azure KeyVault API to set/get secrets from a given Keyvault on Azure"""
    def __init__(self, keyvault_name: str, auth_path: Path):
        """Initialize the Azure Keyvault client

        Args:
            keyvault_name (str, optional): Name of the keyvault. Defaults to None.
            auth_path (Path, optional): Authentication json file path. Defaults to None.
        """
        super(AzureKeyVault, self).__init__(auth_path)

        self.name = keyvault_name
        self.uri = f"https://{self.name}.vault.azure.net"

        self.secret_client = SecretClient(
            vault_url=self.uri,
            credential=self.client_secret_credentials,
            version="7.0")
        self.keyvault_client = KeyVaultManagementClient(
            self.client_secret_credentials, self.subscription_id)

        self.exists = self.name in [
            i.name for i in self.keyvault_client.vaults.list()
        ]

        self.logger.debug(f"Keyvault manager ready: {self.name}")

    def get_secret(self, name: str) -> str:
        """Get secret from keyvault

        Args:
            name (str): name of the secret to get from keyvault

        Returns:
            str: The secret value
        """
        try:
            secret = self.secret_client.get_secret(name)
            self.logger.debug(f"Retrieved secret: {secret.id}")
        except CloudError as e:
            self.logger.error(f"Could not get secret: {name}")
            raise e
        return secret.value

    def set_secret(self, name: str, value: str) -> str:
        """Set secret value in keyvault

        Args:
            name (str): name of the secret to get from keyvault
            value (str): value of the keyvault secret
        """
        try:
            secret = self.secret_client.set_secret(name, value)
            self.logger.debug(f"Set secret: {secret.id}")
        except CloudError as e:
            self.logger.error(f"Could not set secret: {name}")
            raise e
        return secret.value

    def delete_secret(self, name: str, purge: bool = True) -> None:
        """Delete a secret from the key vault

        Args:
            name (str): name of the secret
            purge (bool, optional): whether to purge the secret or soft-delete. Defaults to True.
        """
        poller = self.secret_client.begin_delete_secret(name)
        poller.wait()
        if purge:
            self.secret_client.purge_deleted_secret(name)

    def grant_access(self, rsg: str, subnet_ids: List[str] = None) -> None:
        """Grant access to a keyvault from a list of subnets

        Args:
            rsg (str): Resource group of the key vault
            subnet_ids (List[str], optional): list of subnet IDs. Defaults to None.
        """
        self.logger.info(f"Grant access to KeyVault running for: {self.name}")
        tenant_id = self._get_tenant_id()

        vault = self.keyvault_client.vaults.get(rsg, self.name)
        props = vault.properties
        tenant_update = False

        if (tenant_id not in [
                x.tenant_id for x in vault.properties.access_policies
        ]) or vault.properties.tenant_id != tenant_id:
            tenant_update = True
            props.tenant_id = tenant_id
            props.access_policies.append({
                "tenant_id": tenant_id,
                "object_id": self.get_object_id(),
                "permissions": {
                    "secrets": ["all"]
                },
            })
        if subnet_ids:
            props.network_acls = NetworkRuleSet(
                default_action="Deny",
                ip_rules=[],
                virtual_network_rules=[
                    VirtualNetworkRule(id=i) for i in subnet_ids
                ],
            )
        if subnet_ids or tenant_update:
            kv = self.keyvault_client.vaults.create_or_update(
                rsg,
                self.name,
                {
                    "location": vault.location,
                    "properties": props
                },
            )
            kv.wait()

    def delete_keyvault(self,
                        rsg: str,
                        location: str,
                        purge: bool = True,
                        fail_ok: bool = True) -> None:
        """Delete a key vault

        Args:
            rsg (str): resource group of the vault
            location (str): location of the vault
            purge (bool, optional): whether to purge the vault. Defaults to True.
        """
        self.logger.info(f"Deleting keyvault {self.name}")
        try:
            d = self.keyvault_client.vaults.delete(rsg, self.name)
            if purge:
                self.logger.info(f"Purging keyvault {self.name}")
                p = self.keyvault_client.vaults.begin_purge_deleted(
                    self.name, location)
                p.wait()
        except Exception as e:
            if not fail_ok:
                raise e

        self.exists = False

    def create_keyvault(self,
                        rsg: str,
                        location: str,
                        soft_delete: bool = True,
                        subnet_ids: List[str] = None):
        """Creates a key vault object in Azure

        Args:
            soft_delete (bool, optional): turn on soft-delete. Defaults to True.
            subnet_ids (List[str], optional): subnet IDs to grant access to. Defaults to None.

        Raises:
            RuntimeError: Keyvault name is already taken.
        """
        self.logger.info(f"Create or update KeyVault running for: {self.name}")

        if not self.check_name_available():
            raise RuntimeError(
                "Keyvault name is taken by deleted keyvault or is being used.")

        configuration = {
            "location": location,
            "properties": {
                "sku": {
                    "name": "standard",
                    "family": "A"
                },
                "tenant_id":
                self._get_tenant_id(),
                "enable_soft_delete":
                soft_delete,
                "access_policies": [{
                    "tenant_id": self._get_tenant_id(),
                    "object_id": self.get_object_id(),
                    "permissions": {
                        "keys": ["all"],
                        "secrets": ["all", "purge"]
                    },
                }],
            },
        }

        if subnet_ids:
            configuration["properties"]["network_acls"] = NetworkRuleSet(
                default_action="Deny",
                ip_rules=[],
                virtual_network_rules=[
                    VirtualNetworkRule(id=i) for i in subnet_ids
                ])

        kv = self.keyvault_client.vaults.begin_create_or_update(
            rsg, self.name, configuration)
        kv.wait()

        while True:
            try:
                self.set_secret("test", "x")
            except:
                self.logger.warning(
                    "Waiting for keyvault to come up. Please check connection to the VNET."
                )
                time.sleep(1)
            else:
                self.delete_secret("test")
                break

        self.exists = True

    def check_name_available(self) -> bool:
        """Check if keyvault name is available

        Args:
            name (str): name of the keyvault

        Returns:
            bool: whether the name is available or not
        """

        deleted_vaults = self.keyvault_client.vaults.list_deleted()
        names = [i.name for i in deleted_vaults]
        print(names)

        available = self.keyvault_client.vaults.check_name_availability(
            VaultCheckNameAvailabilityParameters(name=self.name))
        print(available)

        if (self.name in names) or not available.name_available:
            return False
        return True
    if c.name.startswith("livekvtest")
]
for certificate in deleted_test_certificates:
    cert_client.purge_deleted_certificate(certificate.name)

test_keys = [
    k for k in key_client.list_properties_of_keys()
    if k.name.startswith("livekvtest")
]
for key in test_keys:
    key_client.begin_delete_key(key.name).wait()
deleted_test_keys = [
    k for k in key_client.list_deleted_keys()
    if k.name.startswith("livekvtest")
]
for key in deleted_test_keys:
    key_client.purge_deleted_key(key.name)

test_secrets = [
    s for s in secret_client.list_properties_of_secrets()
    if s.name.startswith("livekvtest")
]
for secret in test_secrets:
    secret_client.begin_delete_secret(secret.name).wait()
deleted_test_secrets = [
    s for s in secret_client.list_deleted_secrets()
    if s.name.startswith("livekvtest")
]
for secret in deleted_test_secrets:
    secret_client.purge_deleted_secret(secret.name)