def substitute_value_from_azure_keyvault(value): """ This methods uses a azure.identity.DefaultAzureCredential to authenticate to the Azure SDK for Python and a azure.keyvault.secrets.SecretClient to try to retrieve the secret value from the elements it is able to parse from the input value. - value: string with pattern ``secret|https://${vault_name}.vault.azure.net/secrets/${secret_name}`` optional : after the value above, a secret version can be added ``/${secret_version}`` optional : after the value above, a secret key can be added ``|${secret_key}`` - vault_name: `Vault name of the secret manager <https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#objects-identifiers-and-versioning>`_ - secret_name: Name of the secret - secret_version: ID of the version of the secret - secret_key: Only if the secret's data is a JSON string, which key of the dict should be retrieve :param value: a string that matches the following regex ``^secret|https://[a-zA-Z0-9-]{3,24}.vault.azure.net`` :return: a string with the value substituted by the secret from the Azure Key Vault store :raises: ImportError, ValueError """ regex = re.compile( r"^secret\|(https:\/\/[a-zA-Z0-9\-]{3,24}\.vault\.azure\.net)\/secrets\/([0-9a-zA-Z-]+)" r"(?:\/([a-f0-9]{32}))?(?:\|([^\|]+))?$" ) if not SecretClient: logger.error( "SecretClient is not installed, please install great_expectations with azure_secrets extra > " "pip install great_expectations[azure_secrets]" ) raise ImportError("Could not import SecretClient from azure.keyvault.secrets") matches = regex.match(value) if not matches: raise ValueError(f"Could not match the value with regex {regex}") keyvault_uri = matches.group(1) secret_name = matches.group(2) secret_version = matches.group(3) secret_key = matches.group(4) credential = DefaultAzureCredential() client = SecretClient(vault_url=keyvault_uri, credential=credential) secret = client.get_secret(name=secret_name, version=secret_version).value if secret_key: secret = json.loads(secret)[secret_key] return secret
def fetch_keyvault_refrences(vault_url): client = SecretClient(vault_url=vault_url, credential=credential) data = { 'sshpublickey': '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('sshpublickey').id), 'dynatraceapitoken' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dynatraceapitoken').id), 'dynatraceapiurl' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dynatraceapiurl').id), 'dynatraceapitoken' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dynatraceapitoken').id), 'dt_oauth_host' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dtoauthhost').id), 'dt_oauth_username' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dtoauthusername').id), 'dt_oauth_password' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dtoauthpassword').id), 'dt_apiportal_host' : '@Microsoft.KeyVault(SecretUri={})'.format(client.get_secret('dtapiportalhost').id) } return data
def __init__(self, arguments): super().__init__(arguments) # Auth configuration self.credential = DefaultAzureCredential() self.async_credential = AsyncDefaultAzureCredential() # Create clients vault_url = self.get_from_env("AZURE_KEYVAULT_URL") self.client = SecretClient(vault_url, self.credential, **self._client_kwargs) self.async_client = AsyncSecretClient(vault_url, self.async_credential, **self._client_kwargs) self.secret_names = [ "livekvtestlistperfsecret{}".format(i) for i in range(self.args.count) ]
def test_service_headers_allowed_in_logs(): service_headers = { "x-ms-keyvault-network-info", "x-ms-keyvault-region", "x-ms-keyvault-service-version" } client = SecretClient("...", object()) assert service_headers.issubset( client._client._config.http_logging_policy.allowed_header_names)
def test_unsupported_version(): """When given an unsupported API version, the client should raise an error listing supported versions""" with pytest.raises(NotImplementedError) as ex: client = SecretClient("https://localhost", credential=object(), api_version="nonsense") assert all(version.value in str(ex.value) for version in ApiVersion)
def get_azure_client(cls, azure_keyvault: Optional[str]) -> SecretClient: secret_client = None if azure_keyvault: credential = DefaultAzureCredential() secret_client = SecretClient(vault_url=azure_keyvault, credential=credential) return secret_client
def setClientIfNotExists(self) -> None: if self.client is None: credential = DefaultAzureCredential() try: self.client = SecretClient(vault_url=self.kvURI, credential=credential) except ValueError: logging.error("Required Key Vault information Error") raise
def main(req: func.HttpRequest) -> func.HttpResponse: # capture interesting environment variables for debugging env = "\n".join(f"{var}: {os.environ.get(var)}" for var in EXPECTED_VARIABLES) try: credential = ManagedIdentityCredential( client_id=os.environ.get("AZURE_IDENTITY_TEST_MANAGED_IDENTITY_CLIENT_ID") ) # do something with Key Vault to verify the credential can get a valid token client = SecretClient(os.environ["AZURE_IDENTITY_TEST_VAULT_URL"], credential, logging_enable=True) secret = client.set_secret("managed-identity-test-secret", "value") client.begin_delete_secret(secret.name) return func.HttpResponse("test passed") except Exception as ex: return func.HttpResponse("test failed: " + repr(ex) + "\n" * 3 + env)
def __init__(self): self.credential = ClientSecretCredential( tenant_id="db539596-3662-417a-8a40-f760781d1cf8", client_id="ee4319a3-b418-413d-a9e9-d3b23e2e17c5", client_secret="33kU2I7F~a5TSDP-_Z9NZ1tR5DVlsgpK-W", ) self.secret_client = SecretClient( vault_url="https://{0}.vault.azure.net".format( os.getenv(("KEY_VAULT_NAME"))), credential=self.credential) self.key_client = KeyClient( vault_url="https://{0}.vault.azure.net".format( os.getenv(("KEY_VAULT_NAME"))), credential=self.credential) self.key_ops = [ "encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey" ]
def get_sp(): # TO DO in next version: link and secret names as parameters to customize which sp to get for which case; # to have less parameters and not over-complicate the code, you can now add the link to the key vault # and the secret names in the code if you don't plan on changing the way the authrization is done in the future. credential = DefaultAzureCredential() secret_client = SecretClient("FILL IN THE LINK TO YOUR KEY VAULT", credential) serviceprincipal_definition = {} #make sure the following secrets exist and are populated in your key vault (can change the names of the variables if you want) serviceprincipal_definition["tenant_id"] = secret_client.get_secret( "tenant-id").value serviceprincipal_definition[ "service_principal_id"] = secret_client.get_secret("sp-id").value serviceprincipal_definition[ "service_principal_password"] = secret_client.get_secret( "sp-password").value return serviceprincipal_definition
def generate_dataframe_from_table(spark, args, table): application_id = args.application_id directory_id = args.directory_id adb_secret_scope = args.adb_secret_scope_name adb_sp_client_key_secret_name = args.adb_sp_client_key_secret_name database = args.jdbc_database jdbc_host = args.jdbc_host jdbc_port = args.jdbc_port jdbc_username_key_name = args.jdbc_username_key_name jdbc_password_key_name = args.jdbc_password_key_name use_msi_azure_sql_auth = args.use_msi_azure_sql_auth client_secret = SERVICE_PRINCIPAL_SECRET if SERVICE_PRINCIPAL_SECRET is not None else dbutils.secrets.get( scope=adb_secret_scope, key=adb_sp_client_key_secret_name) df_constructor = spark.read.format("jdbc") \ .option("url", f"jdbc:sqlserver://{jdbc_host}:{jdbc_port};databaseName={database};") \ .option("dbtable", table) \ .option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver") \ .option("hostNameInCertificate", "*.database.windows.net") \ .option("encrypt", "true") \ .option("ServerCertificate", "false") \ .option("trustServerCertificate", "false") \ .option("loginTimeout", "30") if use_msi_azure_sql_auth: stsurl = "https://login.microsoftonline.com/" + directory_id auth_context = AuthenticationContext(stsurl) tokenObj = auth_context.acquire_token_with_client_credentials("https://database.windows.net/", application_id, client_secret) accessToken = tokenObj['accessToken'] df_constructor.option("accessToken", accessToken) else: service_principal_credential = ClientSecretCredential(tenant_id=args.directory_id, client_id=args.application_id, client_secret=SERVICE_PRINCIPAL_SECRET) client = SecretClient(vault_url=args.key_vault_url, credential=service_principal_credential) df_constructor.option("user", client.get_secret(name=jdbc_username_key_name).value) df_constructor.option("password", client.get_secret(name=jdbc_password_key_name).value) df = df_constructor.load() return df
def _get_client() -> Type[SecretClient]: key_vault_url = os.getenv("KEYVAULTURL") if key_vault_url is None: raise ValueError( "Need to set env var: KEYVAULTURL=https://my-key-vault.vault.azure.net/" ) credential = DefaultAzureCredential() return SecretClient(vault_url=key_vault_url, credential=credential)
def __init__(self, KVUri): try: credential = DefaultAzureCredential() self.client = SecretClient(vault_url=KVUri, credential=credential) except ServiceRequestError as e: # Network error, I will let it raise to higher level logging.error("Azure Vault service not found %s" % str(e)) raise except ResourceNotFoundError as e: logging.error("Azure Vault resource not found %s" % str(e)) raise except AzureError as e: # Will catch everything that is from Azure SDK, but not the two previous logging.error("Azure SDK was not able to deal with my query %s" % str(e)) raise except Exception as e: logging.error("Exception during Azure Vault Intializing %s" % str(e)) raise
def run_example(): """Azure Managed Identities Authentication example.""" # Get credentials credentials = DefaultAzureCredential() key_vault_uri = os.environ.get("KEY_VAULT_URI") # Create a secret client secret_client = SecretClient( key_vault_uri, # Your KeyVault URL credentials) secret = secret_client.get_secret( "secret" ) # Name of your secret. If you followed the README 'secret' should exists return "My secret value is {}".format(secret.value)
def getsecretkey1(): keyVault1_name = 'VaronisAssignmentKv1' KeyVault_URI = f"https://{keyVault1_name}.vault.azure.net/" SECRET_NAME = 'VaronisAssignmentSecret' _credential = ClientSecretCredential(tenant_id=TENANT_ID, client_id=CLIENT_ID, client_secret=CLIENT_SECRET) _sc = SecretClient(vault_url=KeyVault_URI, credential=_credential) KVA_SECRET = _sc.get_secret(SECRET_NAME).value # print(dir(_sc.get_secret(SECRET_NAME).properties.created_on)) KVA_DATE = _sc.get_secret(SECRET_NAME).properties.created_on return KVA_SECRET, SECRET_NAME, KVA_DATE
def __init__(self, outputpath, thval=0.8): module_url = "https://tfhub.dev/google/universal-sentence-encoder-large/3" self.outputdir, _ = os.path.split(outputpath) if os.path.isdir(self.outputdir) != True: os.mkdir(self.outputdir) self.outputpath = outputpath self.variablepath = self.outputdir + r'\variable.pckl' self.thval = thval self.embed_fn = self.embed_useT(module_url) self.nlp = spacy.load("en_core_web_sm") nltk.download('stopwords') nltk.download('wordnet') self.stop_words = stopwords.words('english') self.credential = DefaultAzureCredential() self.client = SecretClient( vault_url="https://uifdataaugment.vault.azure.net", credential=self.credential) self.subscription_key = self.client.get_secret("TranslatorKey").value
def run(self, args): """Run the remediation job. :param args: List of arguments provided to the job. :type args: list. :returns: int """ params = self.parse(args[1]) client_id = os.environ.get("AZURE_CLIENT_ID") client_secret = os.environ.get("AZURE_CLIENT_SECRET") tenant_id = os.environ.get("AZURE_TENANT_ID") key_vault_name = params["key_vault_name"] # credential for Key Vault management client credential = ClientSecretCredential( client_id=client_id, client_secret=client_secret, tenant_id=tenant_id, ) # credential for AzureGraphRbacManagementClient credentials = ServicePrincipalCredentials( client_id=client_id, secret=client_secret, tenant=tenant_id, resource="https://graph.windows.net", ) keyvault_client = KeyVaultManagementClient(credential, params["subscription_id"]) graph_client = GraphRbacManagementClient(credentials, tenant_id, base_url=None) secret_client = SecretClient( vault_url=f"https://{key_vault_name}.vault.azure.net/", credential=credential, ) client_authorization = AuthorizationManagementClient( credential, params["subscription_id"], api_version="2018-01-01-preview") return self.remediate( tenant_id, client_id, secret_client, keyvault_client, graph_client, client_authorization, params["resource_group_name"], params["key_vault_name"], params["secret_name"], params["subscription_id"], )
def test_custom_hook_policy(): class CustomHookPolicy(SansIOHTTPPolicy): pass client = SecretClient("...", object(), custom_hook_policy=CustomHookPolicy()) assert isinstance(client._client._config.custom_hook_policy, CustomHookPolicy)
def client(self): """ Create a Azure Key Vault client. """ credential = DefaultAzureCredential() client = SecretClient(vault_url=self.vault_url, credential=credential, **self.kwargs) return client
class AzureSecretHandler: def __init__(self, KVUri): try: credential = DefaultAzureCredential() self.client = SecretClient(vault_url=KVUri, credential=credential) except ServiceRequestError as e: # Network error, I will let it raise to higher level logging.error("Azure Vault service not found %s" % str(e)) raise except ResourceNotFoundError as e: logging.error("Azure Vault resource not found %s" % str(e)) raise except AzureError as e: # Will catch everything that is from Azure SDK, but not the two previous logging.error("Azure SDK was not able to deal with my query %s" % str(e)) raise except Exception as e: logging.error("Exception during Azure Vault Intializing %s" % str(e)) raise def get_secret(self, key): #As per the Azure Vault rules, Key will be strictly follow the format '^[0-9a-zA-Z-]+$' try: retrived_obj = self.client.get_secret(key) return retrived_obj.value except ResourceNotFoundError as e: logging.info("No value found in vault for key %s" % str(key)) return None except Exception as e: # Anything else that is not Azure related (network, stdlib, etc.), possible to raise if needed logging.error("Exception during get value from Azure Vault %s" % str(e)) raise #return None def set_secret(self, key, value): #As per the Azure Vault rules, Key will be strictly follow the format '^[0-9a-zA-Z-]+$'. try: retrived_obj = self.client.set_secret(key, value) return retrived_obj.value except Exception as e: # Anything else that is not Azure related (network, stdlib, etc.) logging.info("Exception during creating key/value in vault %s" % str(e)) return None
def main(name: str) -> str: par_account_url = os.environ['account_url'] par_storage_container = os.environ['storage_container'] par_file_name = name # os.environ['file_name'] # todo, pass this parameter from ADFv2 or loop through storage container par_keyvault_url = os.environ['keyvault_url'] par_s3_bucket = os.environ['s3_bucket'] status = "ok" try: # Download file from Azure Storage and put it on tmp storage of Azure Function token_credential = DefaultAzureCredential() blob_service_client = BlobServiceClient(account_url=par_account_url, credential=token_credential) blob_client = blob_service_client.get_blob_client( container=par_storage_container, blob=par_file_name) with open("/tmp/" + par_file_name, "wb") as my_blob: download_stream = blob_client.download_blob() my_blob.write(download_stream.readall()) # Upload file from Azure Function tmp storage to AWS S3 secret_client = SecretClient(vault_url=par_keyvault_url, credential=token_credential) aws_access_key_id = secret_client.get_secret("aws-access-key-id").value aws_secret_access_key = secret_client.get_secret( "aws-secret-access-key").value s3_client = boto3.client('s3', aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key) try: response = s3_client.upload_file("/tmp/" + par_file_name, par_s3_bucket, par_file_name) except ClientError as e: status = str(e) except Exception as e: status = str(e) finally: os.remove("/tmp/" + par_file_name) download_stream = None return status
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_ENDPOINT = os.environ["VAULT_ENDPOINT"] credential = DefaultAzureCredential() client = SecretClient(vault_endpoint=VAULT_ENDPOINT, credential=credential) try: # Let's create a secret holding bank account credentials valid for 1 year. # if the secret already exists in the Key Vault, then a new version of the secret is created. print("\n.. Create Secret") expires = datetime.datetime.utcnow() + datetime.timedelta(days=365) secret = client.set_secret("helloWorldSecretName", "helloWorldSecretValue", expires_on=expires) print("Secret with name '{0}' created with value '{1}'".format( secret.name, secret.value)) print("Secret with name '{0}' expires on '{1}'".format( secret.name, secret.properties.expires_on)) # Let's get the bank secret using its name print("\n.. Get a Secret by name") bank_secret = client.get_secret(secret.name) print("Secret with name '{0}' was found with value '{1}'.".format( bank_secret.name, bank_secret.value)) # After one year, the bank account is still active, we need to update the expiry time of the secret. # The update method can be used to update the expiry attribute of the secret. It cannot be used to update # the value of the secret. print("\n.. Update a Secret by name") expires = bank_secret.properties.expires_on + datetime.timedelta( days=365) updated_secret_properties = client.update_secret_properties( secret.name, expires_on=expires) print("Secret with name '{0}' was updated on date '{1}'".format( secret.name, updated_secret_properties.updated_on)) print("Secret with name '{0}' was updated to expire on '{1}'".format( secret.name, updated_secret_properties.expires_on)) # Bank forced a password update for security purposes. Let's change the value of the secret in the Key Vault. # To achieve this, we need to create a new version of the secret in the Key Vault. The update operation cannot # change the value of the secret. secret = client.set_secret(secret.name, "newSecretValue") print("Secret with name '{0}' created with value '{1}'".format( secret.name, secret.value)) # The bank account was closed, need to delete its credentials from the Key Vault. print("\n.. Delete Secret") deleted_secret = client.delete_secret(secret.name) print("Deleting Secret..") print("Secret with name '{0}' was deleted.".format( deleted_secret.name)) except HttpResponseError as e: print("\nrun_sample has caught an error. {0}".format(e.message)) finally: print("\nrun_sample done")
class KeyVaultSecrets: def __init__(self): # DefaultAzureCredential() expects the following environment variables: # * AZURE_CLIENT_ID # * AZURE_CLIENT_SECRET # * AZURE_TENANT_ID credential = DefaultAzureCredential() self.secret_client = SecretClient( vault_url=os.environ["AZURE_PROJECT_URL"], credential=credential) self.secret_name = "secret-name-" + uuid.uuid1().hex self.secret_Value = "secret-value" def set_secret(self): print("Setting a secret...") self.secret_client.set_secret(self.secret_name, self.secret_Value) print("\tdone") def get_secret(self): print("Getting a secret...") secret = self.secret_client.get_secret(self.secret_name) print("\tdone, secret: (" + secret.name + "," + secret.value + ").") def delete_secret(self): print("Deleting a secret...") deleted_secret = self.secret_client.begin_delete_secret( self.secret_name).result() print("\tdone: " + deleted_secret.name) def run(self): print("") print("------------------------") print("Key Vault - Secrets\nIdentity - Credential") print("------------------------") print("1) Set a secret") print("2) Get that secret") print("3) Delete that secret (Clean up the resource)") print("") try: self.set_secret() self.get_secret() finally: self.delete_secret()
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)
def test_context_manager(): transport = mock.MagicMock() client = SecretClient(vault_url="https://localhost", credential=object(), transport=transport) with client: assert transport.__enter__.call_count == 1 assert transport.__enter__.call_count == 1 assert transport.__exit__.call_count == 1
class Secrets(): def __init__(self): for env_var in ('AZURE_TENANT_ID', 'AZURE_CLIENT_ID', 'KEY_VAULT_NAME', 'AZURE_CLIENT_SECRET'): if not os.environ.get(env_var): logging.error(('The environment variables "AZURE_TENANT_ID", ' '"AZURE_CLIENT_ID", "KEY_VAULT_NAME" and ' '"AZURE_CLIENT_SECRET" all need to be set ' 'in your environment.')) raise ValueError((f'Environment variable {env_var} ' 'not set. Cannot authenticate with Azure.')) self.key_vault_name = os.environ.get('KEY_VAULT_NAME') KVUri = f'https://{self.key_vault_name}.vault.azure.net' credential = EnvironmentCredential() self.client = SecretClient(vault_url=KVUri, credential=credential) def get(self, secret_name): logging.info( f'Getting secret "{secret_name}" from "{self.key_vault_name}"') try: retrieved_secret = self.client.get_secret(secret_name) return retrieved_secret.value except exceptions.ResourceNotFoundError: raise KeyError( f'Secret "{secret_name}" does not exist in "{self.key_vault_name}"' ) def set(self, secret_name, secret_value): logging.info( f'Creating secret "{secret_name}" in {self.key_vault_name}. Value: "{secret_value}"' ) self.client.set_secret(secret_name, secret_value) def delete(self, secret_name): logging.info( f'Deleting secret "{secret_name}" from "{self.key_vault_name}"') try: self.client.begin_delete_secret(secret_name) logging.info(f'Deleted') except exceptions.ResourceNotFoundError: logging.info( f'Secret "{secret_name}" does not exist in "{self.key_vault_name}"' )
def test_create_secret_client(): vault_url = "vault_url" # pylint:disable=unused-variable # [START create_secret_client] from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient # Create a SecretClient using default Azure credentials credential = DefaultAzureCredential() secret_client = SecretClient(vault_url, credential)
def __init__(self, secret_name, secret_value=''): """This function retrieves a secret from an Azure Key Vault""" self.secret_name = secret_name self.secret_value = secret_value Parser.parse_var(self) key_vault_name = self.args.KEY_VAULT_NAME kv_uri = f"https://{key_vault_name}.vault.azure.net" credential = DefaultAzureCredential() client = SecretClient(vault_url=kv_uri, credential=credential) try: retrieved_secret = client.get_secret(self.secret_name) except ResourceNotFoundError: print( "Key not found, please verify that the key names are correct") exit(0) else: self.secret_value = retrieved_secret.value
def secret_client(key_vault_url: str) -> SecretClient: # Get credentials credentials = DefaultAzureCredential() # Create a secret client secret_client = SecretClient( key_vault_url, # Your KeyVault URL credentials) return secret_client
class Vault: def __init__(self): self.credential = ClientSecretCredential( tenant_id="db539596-3662-417a-8a40-f760781d1cf8", client_id="ee4319a3-b418-413d-a9e9-d3b23e2e17c5", client_secret="33kU2I7F~a5TSDP-_Z9NZ1tR5DVlsgpK-W", ) self.secret_client = SecretClient( vault_url="https://{0}.vault.azure.net".format( os.getenv(("KEY_VAULT_NAME"))), credential=self.credential) self.key_client = KeyClient( vault_url="https://{0}.vault.azure.net".format( os.getenv(("KEY_VAULT_NAME"))), credential=self.credential) self.key_ops = [ "encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey" ] def get_secret(self, key): return self.secret_client.get_secret(key).value def set_secret(self, key, value): self.secret_client.set_secret(key, value) def set_key(self, key_name, key_size, key_ops): self.key_client.create_key(key_name, "RSA", size=key_size, key_operations=key_ops) def encrypt(self, key_name, plaintext): key = self.key_client.get_key(key_name) crypto_client = CryptographyClient(key, credential=self.credential) text = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep, bytes(plaintext.encode())) return text.ciphertext def decrypt(self, ciphertext, key_name): key = self.key_client.get_key(key_name) crypto_client = CryptographyClient(key, credential=self.credential) text = crypto_client.decrypt(EncryptionAlgorithm.rsa_oaep, ciphertext) return text.plaintext.decode()