1# Azure Key Vault Certificates client library for Python
2Azure Key Vault helps solve the following problems:
3- Certificate management (this library) - create, manage, and deploy public and private SSL/TLS certificates
4- Cryptographic key management
5([azure-keyvault-keys](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/keyvault/azure-keyvault-keys)) - create, store, and control access to the keys used to encrypt your data
6- Secrets management
7([azure-keyvault-secrets](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/keyvault/azure-keyvault-secrets)) -
8securely store and control access to tokens, passwords, certificates, API keys,
9and other secrets
10- Vault administration ([azure-keyvault-administration](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/keyvault/azure-keyvault-administration)) - role-based access control (RBAC), and vault-level backup and restore options
11
12[Source code][certificates_client_src] | [Package (PyPI)][pypi_package_certificates] | [API reference documentation][reference_docs] | [Product documentation][keyvault_docs] | [Samples][certificates_samples]
13
14## Getting started
15### Install the package
16Install [azure-keyvault-certificates][pypi_package_certificates] and
17[azure-identity][azure_identity_pypi] with [pip][pip]:
18```Bash
19pip install azure-keyvault-certificates azure-identity
20```
21[azure-identity][azure_identity] is used for Azure Active Directory
22authentication as demonstrated below.
23
24### Prerequisites
25* An [Azure subscription][azure_sub]
26* Python 2.7, 3.5.3, or later
27* A Key Vault. If you need to create one, you can use the
28[Azure Cloud Shell][azure_cloud_shell] to create one with these commands
29(replace `"my-resource-group"` and `"my-key-vault"` with your own, unique
30names):
31
32  (Optional) if you want a new resource group to hold the Key Vault:
33  ```sh
34  az group create --name my-resource-group --location westus2
35  ```
36
37  Create the Key Vault:
38  ```Bash
39  az keyvault create --resource-group my-resource-group --name my-key-vault
40  ```
41
42  Output:
43  ```json
44  {
45      "id": "...",
46      "location": "westus2",
47      "name": "my-key-vault",
48      "properties": {
49          "accessPolicies": [...],
50          "createMode": null,
51          "enablePurgeProtection": null,
52          "enableSoftDelete": null,
53          "enabledForDeployment": false,
54          "enabledForDiskEncryption": null,
55          "enabledForTemplateDeployment": null,
56          "networkAcls": null,
57          "provisioningState": "Succeeded",
58          "sku": { "name": "standard" },
59          "tenantId": "...",
60          "vaultUri": "https://my-key-vault.vault.azure.net/"
61      },
62      "resourceGroup": "my-resource-group",
63      "type": "Microsoft.KeyVault/vaults"
64  }
65  ```
66
67  > The `"vaultUri"` property is the `vault_url` used by [CertificateClient][certificate_client_docs]
68
69### Authenticate the client
70This document demonstrates using [DefaultAzureCredential][default_cred_ref]
71to authenticate as a service principal. However, [CertificateClient][certificate_client_docs]
72accepts any [azure-identity][azure_identity] credential. See the
73[azure-identity][azure_identity] documentation for more information about other
74credentials.
75
76#### Create a service principal (optional)
77This [Azure Cloud Shell][azure_cloud_shell] snippet shows how to create a
78new service principal. Before using it, replace "your-application-name" with
79a more appropriate name for your service principal.
80
81Create a service principal:
82```Bash
83az ad sp create-for-rbac --name http://my-application --skip-assignment
84```
85
86> Output:
87> ```json
88> {
89>     "appId": "generated app id",
90>     "displayName": "my-application",
91>     "name": "http://my-application",
92>     "password": "random password",
93>     "tenant": "tenant id"
94> }
95> ```
96
97Use the output to set **AZURE_CLIENT_ID** ("appId" above), **AZURE_CLIENT_SECRET**
98("password" above) and **AZURE_TENANT_ID** ("tenant" above) environment variables.
99The following example shows a way to do this in Bash:
100```Bash
101export AZURE_CLIENT_ID="generated app id"
102export AZURE_CLIENT_SECRET="random password"
103export AZURE_TENANT_ID="tenant id"
104```
105
106Authorize the service principal to perform certificate operations in your Key Vault:
107```Bash
108az keyvault set-policy --name my-key-vault --spn $AZURE_CLIENT_ID --certificate-permissions backup create delete get import list purge recover restore update
109```
110> Possible certificate permissions: backup, create, delete, deleteissuers, get, getissuers, import, list, listissuers, managecontacts, manageissuers, purge, recover, restore, setissuers, update
111
112If you have enabled role-based access control (RBAC) for Key Vault instead, you can find roles like "Key Vault Certificates Officer" in our [RBAC guide][rbac_guide].
113
114#### Create a client
115Once the **AZURE_CLIENT_ID**, **AZURE_CLIENT_SECRET** and
116**AZURE_TENANT_ID** environment variables are set,
117[DefaultAzureCredential][default_cred_ref] will be able to authenticate the
118[CertificateClient][certificate_client_docs].
119
120Constructing the client also requires your vault's URL, which you can
121get from the Azure CLI or the Azure Portal. In the Azure Portal, this URL is
122the vault's "DNS Name".
123
124```python
125from azure.identity import DefaultAzureCredential
126from azure.keyvault.certificates import CertificateClient
127
128credential = DefaultAzureCredential()
129
130certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
131```
132
133## Key concepts
134### Certificate Client
135With a [CertificateClient][certificate_client_docs] you can get certificates from the vault, create new certificates and
136new versions of existing certificates, update certificate metadata, and delete certificates. You
137can also manage certificate issuers, contacts, and management policies of certificates. This is
138illustrated in the [examples](#examples) below.
139
140## Examples
141This section contains code snippets covering common tasks:
142* [Create a Certificate](#create-a-certificate "Create a Certificate")
143* [Retrieve a Certificate](#retrieve-a-certificate "Retrieve a Certificate")
144* [Update Properties of an existing Certificate](#update-properties-of-an-existing-certificate "Update Properties of an existing Certificate")
145* [Delete a Certificate](#delete-a-certificate "Delete a Certificate")
146* [List Properites of Certificates](#list-properties-of-certificates "List Properties of Certificates")
147* [Asynchronously create a Certificate](#asynchronously-create-a-certificate "Asynchronously create a Certificate")
148* [Asynchronously list properties of Certificates](#asynchronously-list-properties-of-certificates "Asynchronously list properties of Certificates")
149
150### Create a Certificate
151[begin_create_certificate](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.begin_create_certificate)
152creates a certificate to be stored in the Azure Key Vault. If a certificate with the same name already exists, a new
153version of the certificate is created. Before creating a certificate, a management policy for the certificate can be
154created or our default policy will be used. This method returns a long running operation poller.
155```python
156from azure.identity import DefaultAzureCredential
157from azure.keyvault.certificates import CertificateClient, CertificatePolicy
158
159credential = DefaultAzureCredential()
160
161certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
162
163create_certificate_poller = certificate_client.begin_create_certificate(
164    certificate_name="cert-name", policy=CertificatePolicy.get_default()
165)
166print(create_certificate_poller.result())
167```
168If you would like to check the status of your certificate creation, you can call `status()` on the poller or
169[get_certificate_operation](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.get_certificate_operation)
170with the name of the certificate.
171
172### Retrieve a Certificate
173[get_certificate](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.get_certificate)
174retrieves the latest version of a certificate previously stored in the Key Vault.
175```python
176from azure.identity import DefaultAzureCredential
177from azure.keyvault.certificates import CertificateClient
178
179credential = DefaultAzureCredential()
180
181certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
182
183certificate = certificate_client.get_certificate("cert-name")
184
185print(certificate.name)
186print(certificate.properties.version)
187print(certificate.policy.issuer_name)
188```
189
190[get_certificate_version](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.get_certificate_version)
191retrieves a specific version of a certificate.
192```python
193from azure.identity import DefaultAzureCredential
194from azure.keyvault.certificates import CertificateClient
195
196credential = DefaultAzureCredential()
197
198certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
199certificate = certificate_client.get_certificate_version(certificate_name="cert-name", version="cert-version")
200
201print(certificate.name)
202print(certificate.properties.version)
203```
204
205### Update properties of an existing Certificate
206[update_certificate_properties](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.update_certificate_properties)
207updates a certificate previously stored in the Key Vault.
208```python
209from azure.identity import DefaultAzureCredential
210from azure.keyvault.certificates import CertificateClient
211
212credential = DefaultAzureCredential()
213
214certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
215
216# we will now disable the certificate for further use
217updated_certificate= certificate_client.update_certificate_properties(
218    certificate_name="cert-name", enabled=False
219)
220
221print(updated_certificate.name)
222print(updated_certificate.properties.enabled)
223```
224
225### Delete a Certificate
226[begin_delete_certificate](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.begin_delete_certificate)
227requests Key Vault delete a certificate, returning a poller which allows you to wait for the deletion to finish.
228Waiting is helpful when the vault has [soft-delete][soft_delete] enabled, and you want to purge
229(permanently delete) the certificate as soon as possible. When [soft-delete][soft_delete] is disabled,
230`begin_delete_certificate` itself is permanent.
231
232```python
233from azure.identity import DefaultAzureCredential
234from azure.keyvault.certificates import CertificateClient
235
236credential = DefaultAzureCredential()
237
238certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
239
240deleted_certificate_poller = certificate_client.begin_delete_certificate("cert-name")
241
242deleted_certificate = deleted_certificate_poller.result()
243print(deleted_certificate.name)
244print(deleted_certificate.deleted_on)
245```
246### List properties of Certificates
247[list_properties_of_certificates](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient.list_properties_of_certificates)
248lists the properties of all certificates in the specified Key Vault.
249```python
250from azure.identity import DefaultAzureCredential
251from azure.keyvault.certificates import CertificateClient
252
253credential = DefaultAzureCredential()
254
255certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
256
257certificates = certificate_client.list_properties_of_certificates()
258
259for certificate in certificates:
260    # this list doesn't include versions of the certificates
261    print(certificate.name)
262```
263
264### Async operations
265This library includes a complete async API supported on Python 3.5+. To use it, you must
266first install an async transport, such as [aiohttp](https://pypi.org/project/aiohttp/).
267See
268[azure-core documentation](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/core/azure-core/CLIENT_LIBRARY_DEVELOPER.md#transport)
269for more information.
270
271Async clients and credentials should be closed when they're no longer needed. These
272objects are async context managers and define async `close` methods. For
273example:
274
275```py
276from azure.identity.aio import DefaultAzureCredential
277from azure.keyvault.certificates.aio import CertificateClient
278
279credential = DefaultAzureCredential()
280
281# call close when the client and credential are no longer needed
282client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
283...
284await client.close()
285await credential.close()
286
287# alternatively, use them as async context managers (contextlib.AsyncExitStack can help)
288client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
289async with client:
290  async with credential:
291    ...
292```
293
294### Asynchronously create a Certificate
295[create_certificate](https://aka.ms/azsdk/python/keyvault-certificates/aio/docs#azure.keyvault.certificates.aio.CertificateClient.create_certificate)
296creates a certificate to be stored in the Azure Key Vault. If a certificate with the same name already exists, a new
297version of the certificate is created. Before creating a certificate, a management policy for the certificate can be
298created or our default policy will be used. Awaiting `create_certificate` returns your created certificate if creation
299is successful, and a
300[CertificateOperation](https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateOperation)
301if it is not.
302```python
303from azure.identity.aio import DefaultAzureCredential
304from azure.keyvault.certificates.aio import CertificateClient
305from azure.keyvault.certificates import CertificatePolicy
306
307credential = DefaultAzureCredential()
308
309certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
310
311create_certificate_result = await certificate_client.create_certificate(
312    certificate_name="cert-name", policy=CertificatePolicy.get_default()
313)
314print(create_certificate_result)
315```
316
317### Asynchronously list properties of Certificates
318[list_properties_of_certificates](https://aka.ms/azsdk/python/keyvault-certificates/aio/docs#azure.keyvault.certificates.aio.CertificateClient.list_properties_of_certificates)
319lists all the properties of the certificates in the client's vault:
320```python
321from azure.identity.aio import DefaultAzureCredential
322from azure.keyvault.certificates.aio import CertificateClient
323
324credential = DefaultAzureCredential()
325
326certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
327
328certificates = certificate_client.list_properties_of_certificates()
329async for certificate in certificates:
330    print(certificate.name)
331```
332
333## Troubleshooting
334### General
335Key Vault clients raise exceptions defined in [azure-core][azure_core_exceptions].
336For example, if you try to get a key that doesn't exist in the vault, [CertificateClient][certificate_client_docs]
337raises [ResourceNotFoundError](https://aka.ms/azsdk-python-core-exceptions-resource-not-found-error):
338```python
339from azure.identity import DefaultAzureCredential
340from azure.keyvault.certificates import CertificateClient
341from azure.core.exceptions import ResourceNotFoundError
342
343credential = DefaultAzureCredential()
344certificate_client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
345
346try:
347    certificate_client.get_certificate("which-does-not-exist")
348except ResourceNotFoundError as e:
349    print(e.message)
350```
351### Logging
352This library uses the standard
353[logging](https://docs.python.org/3.5/library/logging.html) library for logging.
354Basic information about HTTP sessions (URLs, headers, etc.) is logged at INFO
355level.
356
357Detailed DEBUG level logging, including request/response bodies and unredacted
358headers, can be enabled on a client with the `logging_enable` argument:
359```py
360from azure.identity import DefaultAzureCredential
361from azure.keyvault.certificates import CertificateClient
362import sys
363import logging
364
365# Create a logger for the 'azure' SDK
366logger = logging.getLogger('azure')
367logger.setLevel(logging.DEBUG)
368
369# Configure a console output
370handler = logging.StreamHandler(stream=sys.stdout)
371logger.addHandler(handler)
372
373credential = DefaultAzureCredential()
374
375# This client will log detailed information about its HTTP sessions, at DEBUG level
376client = CertificateClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential, logging_enable=True)
377```
378
379Network trace logging can also be enabled for any single operation:
380 ```python
381certificate = certificate_client.get_certificate(certificate_name="cert-name", logging_enable=True)
382```
383
384## Next steps
385Several samples are available in the Azure SDK for Python GitHub repository. These samples provide example code for additional Key Vault scenarios:
386* [hello_world.py][hello_world_sample] and [hello_world_async.py][hello_world_async_sample] - create/get/update/delete certificates
387* [backup_restore_operations.py][backup_operations_sample] and [backup_restore_operations_async.py][backup_operations_async_sample] - backup and
388recover certificates
389* [list_operations.py][list_operations_sample] and [list_operations_async.py][list_operations_async_sample] - list certificates
390* [recover_purge_operations.py][recover_purge_operations_sample] and [recover_purge_operations_async.py][recover_purge_operations_async_sample] - recover and purge certificates
391* [issuers.py][issuers_sample] and [issuers_async.py][issuers_async_sample] - manage certificate issuers
392* [contacts.py][contacts_sample] and [contacts_async.py][contacts_async_sample] - manage certificate contacts
393
394###  Additional Documentation
395For more extensive documentation on Azure Key Vault, see the [API reference documentation][reference_docs].
396
397## Contributing
398This project welcomes contributions and suggestions. Most contributions require
399you to agree to a Contributor License Agreement (CLA) declaring that you have
400the right to, and actually do, grant us the rights to use your contribution.
401For details, visit https://cla.microsoft.com.
402
403When you submit a pull request, a CLA-bot will automatically determine whether
404you need to provide a CLA and decorate the PR appropriately (e.g., label,
405comment). Simply follow the instructions provided by the bot. You will only
406need to do this once across all repos using our CLA.
407
408This project has adopted the [Microsoft Open Source Code of Conduct][code_of_conduct].
409For more information, see the
410[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
411contact opencode@microsoft.com with any additional questions or comments.
412
413[default_cred_ref]: https://aka.ms/azsdk/python/identity/docs#azure.identity.DefaultAzureCredential
414[azure_cloud_shell]: https://shell.azure.com/bash
415[azure_core_exceptions]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/core/azure-core#azure-core-library-exceptions
416[azure_identity]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/identity/azure-identity
417[azure_identity_pypi]: https://pypi.org/project/azure-identity/
418[azure_sub]: https://azure.microsoft.com/free/
419[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/
420[backup_operations_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/backup_restore_operations.py
421[backup_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/backup_restore_operations_async.py
422[hello_world_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/hello_world.py
423[hello_world_async_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/hello_world_async.py
424[keyvault_docs]: https://docs.microsoft.com/azure/key-vault/
425[list_operations_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/list_operations.py
426[list_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/list_operations_async.py
427[recover_purge_operations_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/recover_purge_operations.py
428[recover_purge_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/recover_purge_operations_async.py
429[contacts_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/contacts.py
430[contacts_async_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/contacts_async.py
431[issuers_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/issuers.py
432[issuers_async_sample]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/keyvault/azure-keyvault-certificates/samples/issuers_async.py
433[pip]: https://pypi.org/project/pip/
434[pypi_package_certificates]: https://pypi.org/project/azure-keyvault-certificates/
435[certificate_client_docs]: https://aka.ms/azsdk/python/keyvault-certificates/docs#azure.keyvault.certificates.CertificateClient
436[rbac_guide]: https://docs.microsoft.com/azure/key-vault/general/rbac-guide
437[reference_docs]: https://aka.ms/azsdk/python/keyvault-certificates/docs
438[certificates_client_src]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates
439[certificates_samples]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/keyvault/azure-keyvault-certificates/samples
440[soft_delete]: https://docs.microsoft.com/azure/key-vault/key-vault-ovw-soft-delete
441
442![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python%2Fsdk%2Fkeyvault%2Fazure-keyvault-certificates%2FREADME.png)
443