├── requirements.txt ├── LICENSE ├── .gitignore ├── run_all_samples.py ├── key_vault_sample_config.py ├── README.md ├── authentication_sample.py └── key_vault_sample_base.py /requirements.txt: -------------------------------------------------------------------------------- 1 | adal==1.0.2 2 | asn1crypto==0.24.0 3 | azure-common==1.1.12 4 | azure-keyvault==1.0.0 5 | azure-mgmt-keyvault==1.0.0 6 | azure-mgmt-nspkg==2.0.0 7 | azure-mgmt-resource==1.2.2 8 | azure-nspkg==2.0.0 9 | certifi==2018.4.16 10 | cffi==1.11.5 11 | chardet==3.0.4 12 | cryptography==2.2.2 13 | entrypoints==0.2.3 14 | idna==2.7 15 | isodate==0.6.0 16 | keyring==13.1.0 17 | msrest==0.5.1 18 | msrestazure==0.4.33 19 | oauthlib==2.1.0 20 | pycparser==2.18 21 | PyJWT==1.6.4 22 | python-dateutil==2.7.3 23 | pywin32-ctypes==0.1.2 24 | requests==2.19.1 25 | requests-oauthlib==1.0.0 26 | six==1.11.0 27 | urllib3==1.23 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Scott Schaab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # pycharm 104 | .idea 105 | -------------------------------------------------------------------------------- /run_all_samples.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from key_vault_sample_base import run_all_samples 3 | from authentication_sample import AuthenticationSample 4 | from key_vault_sample_config import KeyVaultSampleConfig 5 | 6 | 7 | if __name__ == "__main__": 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('--ci', default=False, action='store_true', help='indicates that only samples which run as part of the ci should be run') 10 | parser.add_argument('--tenant-id', dest='tenant_id', type=str, default=None, help='the tenant id of the tenant in which to run the sample') 11 | parser.add_argument('--subscription-id', dest='subscription_id', type=str, default=None, help='the subscription id of the subscription in which to run the sample') 12 | parser.add_argument('--client-id', dest='client_id', type=str, default=None, help='the client id of the service principal to run the sample') 13 | parser.add_argument('--client-oid', dest='client_oid', type=str, default=None, help='the object id of the service principal to run the sample') 14 | parser.add_argument('--client-secret', dest='client_secret', type=str, default=None, help='the authentication secret of the service principal to run the sample') 15 | parser.add_argument('--samples', nargs='*', type=str, help='names of specific samples to run') 16 | args = parser.parse_args() 17 | 18 | config = KeyVaultSampleConfig() 19 | 20 | if args.tenant_id: 21 | config.tenant_id = args.tenant_id 22 | if args.subscription_id: 23 | config.subscription_id = args.subscription_id 24 | if args.client_id: 25 | config.client_id = args.client_id 26 | if args.client_oid: 27 | config.client_oid = args.client_oid 28 | if args.client_secret: 29 | config.client_secret = args.client_secret 30 | 31 | run_all_samples([AuthenticationSample(config=config)], requested=args.samples or []) 32 | -------------------------------------------------------------------------------- /key_vault_sample_config.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- 2 | # Copyright (c) Microsoft Corporation. All rights reserved. 3 | # Licensed under the MIT License. See License.txt in the project root for 4 | # license information. 5 | # -------------------------------------------------------------------------- 6 | 7 | import os 8 | 9 | 10 | class KeyVaultSampleConfig(object): 11 | """ 12 | Configuration settings for use in Key Vault sample code. Users wishing to run this sample can either set these 13 | values as environment values or simply update the hard-coded values below 14 | 15 | :ivar subscription_id: Azure subscription id for the user intending to run the sample 16 | :vartype subscription_id: str 17 | 18 | :ivar client_id: Azure Active Directory AppID of the Service Principle to run the sample 19 | :vartype client_id: str 20 | 21 | :ivar client_oid: Azure Active Directory Object ID of the Service Principal to run the sample 22 | :vartype client_oid: str 23 | 24 | :ivar tenant_id: Azure Active Directory tenant id of the user intending to run the sample 25 | :vartype tenant_id: str 26 | 27 | :ivar client_secret: Azure Active Directory Application Key to run the sample 28 | :vartype client_secret: str 29 | 30 | :ivar location: Azure regional location on which to execute the sample 31 | :vartype location: str 32 | 33 | :ivar group_name: Azure resource group on which to execute the sample 34 | :vartype group_name: str 35 | """ 36 | 37 | def __init__(self): 38 | # get credential information from the environment or replace the dummy values with your client credentials 39 | self.subscription_id = os.getenv('AZURE_SUBSCRIPTION_ID', '11111111-1111-1111-1111-111111111111') 40 | self.client_id = os.getenv('AZURE_CLIENT_ID', '22222222-2222-2222-2222-222222222222') 41 | self.client_oid = os.getenv('AZURE_CLIENT_OID', '33333333-3333-3333-3333-333333333333') 42 | self.tenant_id = os.getenv('AZURE_TENANT_ID', '44444444-4444-4444-4444-444444444444') 43 | self.client_secret = os.getenv('AZURE_CLIENT_SECRET', 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=') 44 | self.location = os.getenv('AZURE_LOCATION', 'westus') 45 | self.group_name = os.getenv('AZURE_RESOURCE_GROUP', 'azure-key-vault-samples') 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | services: key-vault 3 | platforms: python 4 | author: schaabs 5 | --- 6 | 7 | ***DISCLAIMER: The data plane samples in this repo are for `azure-keyvault`. In the interest of simplifying APIs, `azure-keyvault` and `KeyVaultClient` have been split into separate packages and clients. For samples using these latest packages, please visit:*** 8 | 9 | - [`azure-keyvault-certificates` samples](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-certificates/samples) 10 | - [`azure-keyvault-keys` samples](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-keys/samples) 11 | - [`azure-keyvault-secrets` samples](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-secrets/samples) 12 | 13 | ***This repo is archived since `azure-keyvault-x` packages have become stable. For the latest management plane package, please visit [`azure-mgmt-keyvault`](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-mgmt-keyvault).*** 14 | 15 | ***DISCLAIMER: If you are looking to migrate from `azure-keyvault` to `azure-keyvault-x`, we suggest getting started with the following migration guides:*** 16 | 17 | - [`azure-keyvault-certificates` migration guide](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/keyvault/azure-keyvault-certificates/migration_guide.md) 18 | - [`azure-keyvault-keys` migration guide](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/keyvault/azure-keyvault-keys/migration_guide.md) 19 | - [`azure-keyvault-secrets` migration guide](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/keyvault/azure-keyvault-secrets/migration_guide.md) 20 | 21 | # Authentication samples for Azure Key Vault using the Azure Python SDK 22 | 23 | This Sample repo includes sample code demonstrating common mechanism for authenticating to an Azure Key Vault vault. 24 | 25 | ## Samples in this repo 26 | * authentication_sample.py 27 | * auth_using_service_principle_credentials -- authenticates to an Azure Key Vault vault using AAD service principle credentials 28 | * auth_using_adal_callback -- authenticates to an Azure Key Vault vault by providing a callback to authenticate using adal 29 | 30 | 31 | ## Running The samples 32 | 1. If you don't already have it, [install Python](https://www.python.org/downloads/). 33 | 34 | 2. We recommend using a [virtual environment](https://docs.python.org/3/tutorial/venv.html) to run this example, but it's not mandatory. You can initialize a virtual environment this way: 35 | 36 | ``` 37 | pip install virtualenv 38 | virtualenv mytestenv 39 | cd mytestenv 40 | source bin/activate 41 | ``` 42 | 43 | 3. Clone the repository. 44 | 45 | ``` 46 | git clone https://github.com/Azure-Samples/key-vault-python-authentication.git 47 | ``` 48 | 49 | 4. Install the dependencies using pip. 50 | 51 | ``` 52 | cd key-vault-python-authentication 53 | pip install -r requirements.txt 54 | ``` 55 | 56 | 5. Create an Azure service principal, using 57 | [Azure CLI](http://azure.microsoft.com/documentation/articles/resource-group-authenticate-service-principal-cli/), 58 | [PowerShell](http://azure.microsoft.com/documentation/articles/resource-group-authenticate-service-principal/) 59 | or [Azure Portal](http://azure.microsoft.com/documentation/articles/resource-group-create-service-principal-portal/). 60 | 61 | 6. Export these environment variables into your current shell. 62 | 63 | ``` 64 | export AZURE_TENANT_ID={your tenant id} 65 | export AZURE_CLIENT_ID={your service principal AppID} 66 | export AZURE_CLIENT_OID={your service principal OID} 67 | export AZURE_CLIENT_SECRET={your application key} 68 | export AZURE_SUBSCRIPTION_ID={your subscription id} 69 | ``` 70 | 71 | 7. Run the samples, optionally specifying a space delimited list of specific samples to run. 72 | 73 | ``` 74 | python run_all_samples.py [samplename[ samplename...]] 75 | ``` 76 | 77 | ## Minimum Requirements 78 | Python 2.7, 3.3, or 3.4. 79 | To install Python, please go to https://www.python.org/downloads/ 80 | 81 | ## More information 82 | 83 | * What is Key Vault? - https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis 84 | * Get started with Azure Key Vault - https://docs.microsoft.com/en-us/azure/key-vault/key-vault-get-started 85 | * Azure Key Vault General Documentation - https://docs.microsoft.com/en-us/azure/key-vault/ 86 | * Azure Key Vault REST API Reference - https://docs.microsoft.com/en-us/rest/api/keyvault/ 87 | * Azure SDK for Python Documentation - https://docs.microsoft.com/en-us/python/api/overview/azure/key-vault?view=azure-python 88 | * Azure Active Directory Documenation - https://docs.microsoft.com/en-us/azure/active-directory/ 89 | 90 | # Contributing 91 | 92 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information 93 | see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) 94 | with any additional questions or comments. 95 | -------------------------------------------------------------------------------- /authentication_sample.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- 2 | # Copyright (c) Microsoft Corporation. All rights reserved. 3 | # Licensed under the MIT License. See License.txt in the project root for 4 | # license information. 5 | # -------------------------------------------------------------------------- 6 | # This script expects that the following environment vars are set, or they can be hardcoded in key_vault_sample_config, these values 7 | # SHOULD NOT be hardcoded in any code derived from this sample: 8 | # 9 | # AZURE_TENANT_ID: with your Azure Active Directory tenant id or domain 10 | # AZURE_CLIENT_ID: with your Azure Active Directory Service Principal AppId 11 | # AZURE_CLIENT_OID: with your Azure Active Directory Service Principle Object ID 12 | # AZURE_CLIENT_SECRET: with your Azure Active Directory Application Key 13 | # AZURE_SUBSCRIPTION_ID: with your Azure Subscription Id 14 | # 15 | # These are read from the environment and exposed through the KeyVaultSampleConfig class. For more information please 16 | # see the implementation in key_vault_sample_config.py 17 | 18 | import sys 19 | from key_vault_sample_base import KeyVaultSampleBase, keyvaultsample, get_name, run_all_samples 20 | from azure.common.credentials import ServicePrincipalCredentials 21 | from azure.keyvault import KeyVaultClient, KeyVaultAuthentication 22 | from azure.keyvault import KeyVaultId 23 | 24 | 25 | class AuthenticationSample(KeyVaultSampleBase): 26 | """ 27 | A collection of samples that demonstrate authenticating with the KeyVaultClient and KeyVaultManagementClient 28 | """ 29 | 30 | @keyvaultsample 31 | def auth_using_service_principle_credentials(self): 32 | """ 33 | authenticates to the Azure Key Vault service using AAD service principle credentials 34 | """ 35 | # create a vault to validate authentication with the KeyVaultClient 36 | vault = self.create_vault() 37 | 38 | # create the service principle credentials used to authenticate the client 39 | credentials = ServicePrincipalCredentials(client_id=self.config.client_id, 40 | secret=self.config.client_secret, 41 | tenant=self.config.tenant_id) 42 | 43 | # create the client using the created credentials 44 | client = KeyVaultClient(credentials) 45 | 46 | # set and get a secret from the vault to validate the client is authenticated 47 | print('creating secret...') 48 | secret_bundle = client.set_secret(vault.properties.vault_uri, 'auth-sample-secret', 'client is authenticated to the vault') 49 | print(secret_bundle) 50 | 51 | print('getting secret...') 52 | secret_bundle = client.get_secret(vault.properties.vault_uri, 'auth-sample-secret', secret_version=KeyVaultId.version_none) 53 | print(secret_bundle) 54 | 55 | @keyvaultsample 56 | def auth_using_adal_callback(self): 57 | """ 58 | authenticates to the Azure Key Vault by providing a callback to authenticate using adal 59 | """ 60 | # create a vault to validate authentication with the KeyVaultClient 61 | vault = self.create_vault() 62 | 63 | import adal 64 | 65 | # create an adal authentication context 66 | auth_context = adal.AuthenticationContext('https://login.microsoftonline.com/%s' % self.config.tenant_id) 67 | 68 | # create a callback to supply the token type and access token on request 69 | def adal_callback(server, resource, scope): 70 | token = auth_context.acquire_token_with_client_credentials(resource=resource, 71 | client_id=self.config.client_id, 72 | client_secret=self.config.client_secret) 73 | return token['tokenType'], token['accessToken'] 74 | 75 | # create a KeyVaultAuthentication instance which will callback to the supplied adal_callback 76 | auth = KeyVaultAuthentication(adal_callback) 77 | 78 | # create the KeyVaultClient using the created KeyVaultAuthentication instance 79 | client = KeyVaultClient(auth) 80 | 81 | # set and get a secret from the vault to validate the client is authenticated 82 | print('creating secret...') 83 | secret_bundle = client.set_secret(vault.properties.vault_uri, 'auth-sample-secret', 'client is authenticated to the vault') 84 | print(secret_bundle) 85 | 86 | print('getting secret...') 87 | secret_bundle = client.get_secret(vault.properties.vault_uri, 'auth-sample-secret', secret_version=KeyVaultId.version_none) 88 | print(secret_bundle) 89 | 90 | @keyvaultsample 91 | def auth_user_with_device_code(self): 92 | """ 93 | authenticates to the Azure Key Vault by providing a callback to authenticate using adal 94 | """ 95 | # create a vault to validate authentication with the KeyVaultClient 96 | vault = self.create_vault() 97 | 98 | import adal 99 | 100 | # create an adal authentication context 101 | auth_context = adal.AuthenticationContext('https://login.microsoftonline.com/%s' % self.config.tenant_id) 102 | 103 | # using the XPlat command line client id as it is available across all tenants and subscriptions 104 | # this would be replaced by your app id 105 | xplat_client_id = '04b07795-8ddb-461a-bbee-02f9e1bf7b46' 106 | 107 | # create a callback to supply the token type and access token on request 108 | def adal_callback(server, resource, scope): 109 | user_code_info = auth_context.acquire_user_code(resource, 110 | xplat_client_id) 111 | 112 | print(user_code_info['message']) 113 | token = auth_context.acquire_token_with_device_code(resource=resource, 114 | client_id=xplat_client_id, 115 | user_code_info=user_code_info) 116 | return token['tokenType'], token['accessToken'] 117 | 118 | # create a KeyVaultAuthentication instance which will callback to the supplied adal_callback 119 | auth = KeyVaultAuthentication(adal_callback) 120 | 121 | # create the KeyVaultClient using the created KeyVaultAuthentication instance 122 | client = KeyVaultClient(auth) 123 | 124 | # set and get a secret from the vault to validate the client is authenticated 125 | print('creating secret...') 126 | secret_bundle = client.set_secret(vault.properties.vault_uri, 'auth-sample-secret', 'client is authenticated to the vault') 127 | print(secret_bundle) 128 | 129 | print('getting secret...') 130 | secret_bundle = client.get_secret(vault.properties.vault_uri, 'auth-sample-secret', secret_version=KeyVaultId.version_none) 131 | print(secret_bundle) 132 | 133 | 134 | if __name__ == "__main__": 135 | sys.exit(run_all_samples([AuthenticationSample()])) 136 | -------------------------------------------------------------------------------- /key_vault_sample_base.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- 2 | # Copyright (c) Microsoft Corporation. All rights reserved. 3 | # Licensed under the MIT License. See License.txt in the project root for 4 | # license information. 5 | # -------------------------------------------------------------------------- 6 | import sys 7 | import os 8 | import time 9 | import json 10 | import inspect 11 | import traceback 12 | import azure.mgmt.keyvault.models 13 | import azure.keyvault.models 14 | from random import Random 15 | from key_vault_sample_config import KeyVaultSampleConfig 16 | from azure.mgmt.resource import ResourceManagementClient 17 | from azure.mgmt.keyvault import KeyVaultManagementClient 18 | from azure.keyvault import KeyVaultClient, KeyVaultAuthentication 19 | from msrest.exceptions import ClientRequestError 20 | from msrestazure.azure_active_directory import ServicePrincipalCredentials 21 | from msrest.paging import Paged 22 | from msrest.serialization import Serializer 23 | from azure.mgmt.keyvault.models import AccessPolicyEntry, VaultProperties, Sku, KeyPermissions, SecretPermissions, \ 24 | CertificatePermissions, Permissions, VaultCreateOrUpdateParameters 25 | 26 | SECRET_PERMISSIONS_ALL = [perm.value for perm in SecretPermissions] 27 | KEY_PERMISSIONS_ALL = [perm.value for perm in KeyPermissions] 28 | CERTIFICATE_PERMISSIONS_ALL = [perm.value for perm in CertificatePermissions] 29 | 30 | _rand = Random() 31 | _failed = [] 32 | 33 | 34 | def get_name(base): 35 | """ 36 | randomly builds a unique name for an entity beginning with the specified base 37 | :param base: the prefix for the generated name 38 | :return: a random unique name 39 | """ 40 | name = '{}-{}-{}'.format(base, _rand.choice(adjectives), _rand.choice(nouns)) 41 | if len(name) < 22: 42 | name += '-' 43 | for i in range(min(5, 23 - len(name))): 44 | name += str(_rand.choice(range(10))) 45 | return name 46 | 47 | 48 | def keyvaultsample(f): 49 | """ 50 | decorator function for marking key vault sample methods 51 | """ 52 | def wrapper(self): 53 | try: 54 | print('--------------------------------------------------------------------') 55 | print('RUNNING: {}'.format(f.__name__)) 56 | print('--------------------------------------------------------------------') 57 | self.setup_sample() 58 | f(self) 59 | except Exception as e: 60 | print('ERROR: running sample failed with raised exception:') 61 | traceback.print_exception(type(e), e, getattr(e, '__traceback__', None)) 62 | _failed.append(f.__name__) 63 | wrapper.__name__ = f.__name__ 64 | wrapper.__doc__ = f.__doc__ 65 | wrapper.kv_sample = True 66 | return wrapper 67 | 68 | 69 | def run_all_samples(samples, requested=None): 70 | """ 71 | runs all sample methods (methods marked with @keyvaultsample) on the specified samples objects, 72 | filtering to any sample methods specified on the command line 73 | :param samples: a list of sample objects 74 | :return: None 75 | """ 76 | requested_samples = requested if requested is not None else sys.argv[1:] 77 | sample_funcs = [] 78 | 79 | for s in samples: 80 | class_samples = {name: func for name, func in s.samples if not requested_samples or name in requested_samples} 81 | if class_samples: 82 | mod_name = os.path.basename(sys.modules[s.__module__].__file__) 83 | print('\n{}:\n'.format(mod_name)) 84 | for name, func in class_samples.items(): 85 | print('\t{} -- {}'.format(name, func.__doc__.strip())) 86 | sample_funcs.append(func) 87 | 88 | for f in sample_funcs: 89 | f() 90 | 91 | return len(_failed) 92 | 93 | 94 | class KeyVaultSampleBase(object): 95 | """Base class for Key Vault samples, provides common functionality needed across Key Vault sample code 96 | 97 | :ivar config: Azure subscription id for the user intending to run the sample 98 | :vartype config: :class: `KeyVaultSampleConfig`q 99 | 100 | :ivar credentials: Azure Active Directory credentials used to authenticate with Azure services 101 | :vartype credentials: :class: `ServicePrincipalCredentials 102 | ` 103 | 104 | :ivar keyvault_data_client: Key Vault data client used for interacting with key vaults 105 | :vartype keyvault_data_client: :class: `KeyVaultClient ` 106 | 107 | :ivar keyvault_mgmt_client: Key Vault management client used for creating and managing key vaults 108 | :vartype keyvault_mgmt_client: :class: `KeyVaultManagementClient ` 109 | 110 | :ivar resource_mgmt_client: Azure resource management client used for managing azure resources, access, and groups 111 | :vartype resource_mgmt_client: :class: `ResourceManagementClient ` 112 | """ 113 | def __init__(self, config=None): 114 | self.config = config or KeyVaultSampleConfig() 115 | self.credentials = None 116 | self.keyvault_data_client = None 117 | self.keyvault_mgmt_client = None 118 | self.resource_mgmt_client = None 119 | self._setup_complete = False 120 | self.samples = {(name, m) for name, m in inspect.getmembers(self) if getattr(m, 'kv_sample', False)} 121 | models = {} 122 | models.update({k: v for k, v in azure.keyvault.models.__dict__.items() if isinstance(v, type)}) 123 | models.update({k: v for k, v in azure.mgmt.keyvault.models.__dict__.items() if isinstance(v, type)}) 124 | self._serializer = Serializer(models) 125 | 126 | def setup_sample(self): 127 | """ 128 | Provides common setup for Key Vault samples, such as creating rest clients, creating a sample resource group 129 | if needed, and ensuring proper access for the service principal. 130 | 131 | :return: None 132 | """ 133 | if not self._setup_complete: 134 | self.mgmt_creds = ServicePrincipalCredentials(client_id=self.config.client_id, secret=self.config.client_secret, 135 | tenant=self.config.tenant_id) 136 | self.data_creds = ServicePrincipalCredentials(client_id=self.config.client_id, secret=self.config.client_secret, 137 | tenant=self.config.tenant_id) 138 | self.resource_mgmt_client = ResourceManagementClient(self.mgmt_creds, self.config.subscription_id) 139 | 140 | # ensure the service principle has key vault as a valid provider 141 | self.resource_mgmt_client.providers.register('Microsoft.KeyVault') 142 | 143 | # ensure the intended resource group exists 144 | self.resource_mgmt_client.resource_groups.create_or_update(self.config.group_name, {'location': self.config.location}) 145 | 146 | self.keyvault_mgmt_client = KeyVaultManagementClient(self.mgmt_creds, self.config.subscription_id) 147 | 148 | self.keyvault_data_client = KeyVaultClient(self.data_creds) 149 | 150 | self._setup_complete = True 151 | 152 | 153 | def create_vault(self): 154 | """ 155 | Creates a new key vault with a unique name, granting full permissions to the current credentials 156 | :return: a newly created key vault 157 | :rtype: :class:`Vault ` 158 | """ 159 | vault_name = get_name('vault') 160 | 161 | # setup vault permissions for the access policy for the sample service principle 162 | permissions = Permissions() 163 | permissions.keys = KEY_PERMISSIONS_ALL 164 | permissions.secrets = SECRET_PERMISSIONS_ALL 165 | permissions.certificates = CERTIFICATE_PERMISSIONS_ALL 166 | 167 | policy = AccessPolicyEntry(tenant_id=self.config.tenant_id, 168 | object_id=self.config.client_oid, 169 | permissions=permissions) 170 | 171 | properties = VaultProperties(tenant_id=self.config.tenant_id, 172 | sku=Sku(name='standard'), 173 | access_policies=[policy]) 174 | 175 | parameters = VaultCreateOrUpdateParameters(location=self.config.location, properties=properties) 176 | parameters.properties.enabled_for_deployment = True 177 | parameters.properties.enabled_for_disk_encryption = True 178 | parameters.properties.enabled_for_template_deployment = True 179 | 180 | print('creating vault {}'.format(vault_name)) 181 | 182 | vault = self.keyvault_mgmt_client.vaults.create_or_update(self.config.group_name, vault_name, parameters).result() 183 | 184 | print('created vault {} {}'.format(vault_name, vault.properties.vault_uri)) 185 | 186 | return vault 187 | 188 | def _serialize(self, obj): 189 | if isinstance(obj, Paged): 190 | serialized = [self._serialize(i) for i in list(obj)] 191 | else: 192 | serialized = self._serializer.body(obj, type(obj).__name__) 193 | return json.dumps(serialized, indent=4, separators=(',', ': ')) 194 | 195 | 196 | adjectives = ['able', 'acid', 'adept', 'aged', 'agile', 'ajar', 'alert', 'alive', 'all', 'ample', 197 | 'angry', 'antsy', 'any', 'apt', 'arid', 'awake', 'aware', 'back', 'bad', 'baggy', 198 | 'bare', 'basic', 'batty', 'beefy', 'bent', 'best', 'big', 'black', 'bland', 'blank', 199 | 'bleak', 'blind', 'blond', 'blue', 'bogus', 'bold', 'bony', 'bossy', 'both', 'bowed', 200 | 'brave', 'brief', 'brisk', 'brown', 'bulky', 'bumpy', 'burly', 'busy', 'cagey', 'calm', 201 | 'cheap', 'chief', 'clean', 'close', 'cold', 'cool', 'corny', 'crazy', 'crisp', 'cruel', 202 | 'curvy', 'cut', 'cute', 'damp', 'dark', 'dead', 'dear', 'deep', 'dense', 'dim', 203 | 'dirty', 'dizzy', 'dopey', 'drab', 'dry', 'dual', 'dull', 'dull', 'each', 'eager', 204 | 'early', 'easy', 'elite', 'empty', 'equal', 'even', 'every', 'evil', 'fair', 'fake', 205 | 'far', 'fast', 'fat', 'few', 'fine', 'firm', 'five', 'flat', 'fond', 'four', 206 | 'free', 'full', 'fuzzy', 'gamy', 'glib', 'glum', 'good', 'gray', 'grey', 'grim', 207 | 'half', 'half', 'hard', 'high', 'hot', 'huge', 'hurt', 'icky', 'icy', 'ideal', 208 | 'ideal', 'idle', 'ill', 'itchy', 'jaded', 'joint', 'juicy', 'jumbo', 'jumpy', 'jumpy', 209 | 'keen', 'key', 'kind', 'known', 'kooky', 'kosher', 'lame', 'lame', 'lanky', 'large', 210 | 'last', 'late', 'lazy', 'leafy', 'lean', 'left', 'legal', 'lewd', 'light', 'like', 211 | 'limp', 'lined', 'live', 'livid', 'lone', 'long', 'loose', 'lost', 'loud', 'low', 212 | 'loyal', 'lumpy', 'lush', 'mad', 'major', 'male', 'many', 'mealy', 'mean', 'meaty', 213 | 'meek', 'mere', 'merry', 'messy', 'mild', 'milky', 'minor', 'minty', 'misty', 'mixed', 214 | 'moist', 'moody', 'moral', 'muddy', 'murky', 'mushy', 'musty', 'mute', 'muted', 'naive', 215 | 'nasty', 'near', 'neat', 'new', 'next', 'nice', 'nice', 'nine', 'nippy', 'nosy', 216 | 'noted', 'novel', 'null', 'numb', 'nutty', 'obese', 'odd', 'oily', 'old', 'one', 217 | 'only', 'open', 'other', 'our', 'oval', 'pale', 'past', 'perky', 'pesky', 'petty', 218 | 'phony', 'pink', 'plump', 'plush', 'poor', 'posh', 'prime', 'prize', 'proud', 'puny', 219 | 'pure', 'pushy', 'pushy', 'quick', 'quiet', 'rainy', 'rapid', 'rare', 'rash', 'raw', 220 | 'ready', 'real', 'red', 'regal', 'rich', 'right', 'rigid', 'ripe', 'rosy', 'rough', 221 | 'rowdy', 'rude', 'runny', 'sad', 'safe', 'salty', 'same', 'sandy', 'sane', 'scaly', 222 | 'shady', 'shaky', 'sharp', 'shiny', 'short', 'showy', 'shut', 'shy', 'sick', 'silky', 223 | 'six', 'slim', 'slimy', 'slow', 'small', 'smart', 'smug', 'soft', 'solid', 'some', 224 | 'sore', 'soupy', 'sour', 'sour', 'spicy', 'spiky', 'spry', 'staid', 'stale', 'stark', 225 | 'steel', 'steep', 'stiff', 'stout', 'sunny', 'super', 'sweet', 'swift', 'tall', 'tame', 226 | 'tan', 'tart', 'tasty', 'taut', 'teeny', 'ten', 'tepid', 'testy', 'that', 'these', 227 | 'thick', 'thin', 'third', 'this', 'those', 'tidy', 'tiny', 'torn', 'total', 'tough', 228 | 'trim', 'true', 'tubby', 'twin', 'two', 'ugly', 'unfit', 'upset', 'urban', 'used', 229 | 'used', 'utter', 'vague', 'vain', 'valid', 'vapid', 'vast', 'vexed', 'vital', 'vivid', 230 | 'wacky', 'wan', 'warm', 'wary', 'wavy', 'weak', 'weary', 'wee', 'weepy', 'weird', 231 | 'wet', 'which', 'white', 'whole', 'wide', 'wild', 'windy', 'wiry', 'wise', 'witty', 232 | 'woozy', 'wordy', 'worn', 'worse', 'worst', 'wrong', 'wry', 'yummy', 'zany', 'zesty', 233 | 'zonked'] 234 | 235 | nouns = ['abroad', 'abuse', 'access', 'act', 'action', 'active', 'actor', 'adult', 'advice', 'affair', 236 | 'affect', 'age', 'agency', 'agent', 'air', 'alarm', 'amount', 'anger', 'angle', 'animal', 237 | 'annual', 'answer', 'appeal', 'apple', 'area', 'arm', 'army', 'art', 'aside', 'ask', 238 | 'aspect', 'assist', 'attack', 'author', 'award', 'baby', 'back', 'bad', 'bag', 'bake', 239 | 'ball', 'band', 'bank', 'bar', 'base', 'basis', 'basket', 'bat', 'bath', 'battle', 240 | 'beach', 'bear', 'beat', 'bed', 'beer', 'being', 'bell', 'belt', 'bench', 'bend', 241 | 'bet', 'beyond', 'bid', 'big', 'bike', 'bill', 'bird', 'birth', 'bit', 'bite', 242 | 'bitter', 'black', 'blame', 'blank', 'blind', 'block', 'blood', 'blow', 'blue', 'board', 243 | 'boat', 'body', 'bone', 'bonus', 'book', 'boot', 'border', 'boss', 'bother', 'bottle', 244 | 'bottom', 'bowl', 'box', 'boy', 'brain', 'branch', 'brave', 'bread', 'break', 'breast', 245 | 'breath', 'brick', 'bridge', 'brief', 'broad', 'brown', 'brush', 'buddy', 'budget', 'bug', 246 | 'bunch', 'burn', 'bus', 'button', 'buy', 'buyer', 'cable', 'cake', 'call', 'calm', 247 | 'camera', 'camp', 'can', 'cancel', 'cancer', 'candle', 'candy', 'cap', 'car', 'card', 248 | 'care', 'career', 'carpet', 'carry', 'case', 'cash', 'cat', 'catch', 'cause', 'cell', 249 | 'chain', 'chair', 'chance', 'change', 'charge', 'chart', 'check', 'cheek', 'chest', 'child', 250 | 'chip', 'choice', 'church', 'city', 'claim', 'class', 'clerk', 'click', 'client', 'clock', 251 | 'closet', 'cloud', 'club', 'clue', 'coach', 'coast', 'coat', 'code', 'coffee', 'cold', 252 | 'collar', 'common', 'cook', 'cookie', 'copy', 'corner', 'cost', 'count', 'county', 'couple', 253 | 'course', 'court', 'cousin', 'cover', 'cow', 'crack', 'craft', 'crash', 'crazy', 'cream', 254 | 'credit', 'crew', 'cross', 'cry', 'cup', 'curve', 'cut', 'cycle', 'dad', 'damage', 255 | 'dance', 'dare', 'dark', 'data', 'date', 'day', 'dead', 'deal', 'dealer', 'dear', 256 | 'death', 'debate', 'debt', 'deep', 'degree', 'delay', 'demand', 'depth', 'design', 'desire', 257 | 'desk', 'detail', 'device', 'devil', 'diet', 'dig', 'dinner', 'dirt', 'dish', 'disk', 258 | 'divide', 'doctor', 'dog', 'door', 'dot', 'double', 'doubt', 'draft', 'drag', 'drama', 259 | 'draw', 'drawer', 'dream', 'dress', 'drink', 'drive', 'driver', 'drop', 'drunk', 'due', 260 | 'dump', 'dust', 'duty', 'ear', 'earth', 'ease', 'east', 'eat', 'edge', 'editor', 261 | 'effect', 'effort', 'egg', 'employ', 'end', 'energy', 'engine', 'entry', 'equal', 'error', 262 | 'escape', 'essay', 'estate', 'event', 'exam', 'excuse', 'exit', 'expert', 'extent', 'eye', 263 | 'face', 'fact', 'factor', 'fail', 'fall', 'family', 'fan', 'farm', 'farmer', 'fat', 264 | 'father', 'fault', 'fear', 'fee', 'feed', 'feel', 'female', 'few', 'field', 'fight', 265 | 'figure', 'file', 'fill', 'film', 'final', 'finger', 'finish', 'fire', 'fish', 'fix', 266 | 'flight', 'floor', 'flow', 'flower', 'fly', 'focus', 'fold', 'food', 'foot', 'force', 267 | 'form', 'formal', 'frame', 'friend', 'front', 'fruit', 'fuel', 'fun', 'funny', 'future', 268 | 'gain', 'game', 'gap', 'garage', 'garden', 'gas', 'gate', 'gather', 'gear', 'gene', 269 | 'gift', 'girl', 'give', 'glad', 'glass', 'glove', 'goal', 'god', 'gold', 'golf', 270 | 'good', 'grab', 'grade', 'grand', 'grass', 'great', 'green', 'ground', 'group', 'growth', 271 | 'guard', 'guess', 'guest', 'guide', 'guitar', 'guy', 'habit', 'hair', 'half', 'hall', 272 | 'hand', 'handle', 'hang', 'harm', 'hat', 'hate', 'head', 'health', 'heart', 'heat', 273 | 'heavy', 'height', 'hell', 'hello', 'help', 'hide', 'high', 'hire', 'hit', 'hold', 274 | 'hole', 'home', 'honey', 'hook', 'hope', 'horror', 'horse', 'host', 'hotel', 'hour', 275 | 'house', 'human', 'hunt', 'hurry', 'hurt', 'ice', 'idea', 'ideal', 'image', 'impact', 276 | 'income', 'injury', 'insect', 'inside', 'invite', 'iron', 'island', 'issue', 'item', 'jacket', 277 | 'job', 'join', 'joint', 'joke', 'judge', 'juice', 'jump', 'junior', 'jury', 'keep', 278 | 'key', 'kick', 'kid', 'kill', 'kind', 'king', 'kiss', 'knee', 'knife', 'lab', 279 | 'lack', 'ladder', 'lady', 'lake', 'land', 'laugh', 'law', 'lawyer', 'lay', 'layer', 280 | 'lead', 'leader', 'league', 'leave', 'leg', 'length', 'lesson', 'let', 'letter', 'level', 281 | 'lie', 'life', 'lift', 'light', 'limit', 'line', 'link', 'lip', 'list', 'listen', 282 | 'living', 'load', 'loan', 'local', 'lock', 'log', 'long', 'look', 'loss', 'love', 283 | 'low', 'luck', 'lunch', 'mail', 'main', 'major', 'make', 'male', 'mall', 'man', 284 | 'manner', 'many', 'map', 'march', 'mark', 'market', 'master', 'match', 'mate', 'math', 285 | 'matter', 'maybe', 'meal', 'meat', 'media', 'medium', 'meet', 'member', 'memory', 'menu', 286 | 'mess', 'metal', 'method', 'middle', 'might', 'milk', 'mind', 'mine', 'minor', 'minute', 287 | 'mirror', 'miss', 'mix', 'mobile', 'mode', 'model', 'mom', 'moment', 'money', 'month', 288 | 'mood', 'most', 'mother', 'motor', 'mouse', 'mouth', 'move', 'movie', 'mud', 'muscle', 289 | 'music', 'nail', 'name', 'nasty', 'nation', 'native', 'nature', 'neat', 'neck', 'nerve', 290 | 'net', 'news', 'night', 'nobody', 'noise', 'normal', 'north', 'nose', 'note', 'notice', 291 | 'novel', 'number', 'nurse', 'object', 'offer', 'office', 'oil', 'one', 'option', 'orange', 292 | 'order', 'other', 'oven', 'owner', 'pace', 'pack', 'page', 'pain', 'paint', 'pair', 293 | 'panic', 'paper', 'parent', 'park', 'part', 'party', 'pass', 'past', 'path', 'pause', 294 | 'pay', 'peace', 'peak', 'pen', 'people', 'period', 'permit', 'person', 'phase', 'phone', 295 | 'photo', 'phrase', 'piano', 'pick', 'pie', 'piece', 'pin', 'pipe', 'pitch', 'pizza', 296 | 'place', 'plan', 'plane', 'plant', 'plate', 'play', 'player', 'plenty', 'poem', 'poet', 297 | 'poetry', 'point', 'police', 'policy', 'pool', 'pop', 'post', 'pot', 'potato', 'pound', 298 | 'power', 'press', 'price', 'pride', 'priest', 'print', 'prior', 'prize', 'profit', 'prompt', 299 | 'proof', 'public', 'pull', 'punch', 'purple', 'push', 'put', 'queen', 'quiet', 'quit', 300 | 'quote', 'race', 'radio', 'rain', 'raise', 'range', 'rate', 'ratio', 'raw', 'reach', 301 | 'read', 'reason', 'recipe', 'record', 'red', 'refuse', 'region', 'regret', 'relief', 'remote', 302 | 'remove', 'rent', 'repair', 'repeat', 'reply', 'report', 'resist', 'resort', 'rest', 'result', 303 | 'return', 'reveal', 'review', 'reward', 'rice', 'rich', 'ride', 'ring', 'rip', 'rise', 304 | 'risk', 'river', 'road', 'rock', 'role', 'roll', 'roof', 'room', 'rope', 'rough', 305 | 'round', 'row', 'royal', 'rub', 'ruin', 'rule', 'run', 'rush', 'sad', 'safe', 306 | 'safety', 'sail', 'salad', 'salary', 'sale', 'salt', 'sample', 'sand', 'save', 'scale', 307 | 'scene', 'scheme', 'school', 'score', 'screen', 'screw', 'script', 'sea', 'search', 'season', 308 | 'seat', 'second', 'secret', 'sector', 'self', 'sell', 'senior', 'sense', 'series', 'serve', 309 | 'set', 'sex', 'shake', 'shame', 'shape', 'share', 'she', 'shift', 'shine', 'ship', 310 | 'shirt', 'shock', 'shoe', 'shoot', 'shop', 'shot', 'show', 'shower', 'sick', 'side', 311 | 'sign', 'signal', 'silly', 'silver', 'simple', 'sing', 'singer', 'single', 'sink', 'sir', 312 | 'sister', 'site', 'size', 'skill', 'skin', 'skirt', 'sky', 'sleep', 'slice', 'slide', 313 | 'slip', 'smell', 'smile', 'smoke', 'snow', 'sock', 'soft', 'soil', 'solid', 'son', 314 | 'song', 'sort', 'sound', 'soup', 'source', 'south', 'space', 'spare', 'speech', 'speed', 315 | 'spell', 'spend', 'spirit', 'spite', 'split', 'sport', 'spot', 'spray', 'spread', 'spring', 316 | 'square', 'stable', 'staff', 'stage', 'stand', 'star', 'start', 'state', 'status', 'stay', 317 | 'steak', 'steal', 'step', 'stick', 'still', 'stock', 'stop', 'store', 'storm', 'story', 318 | 'strain', 'street', 'stress', 'strike', 'string', 'strip', 'stroke', 'studio', 'study', 'stuff', 319 | 'stupid', 'style', 'suck', 'sugar', 'suit', 'summer', 'sun', 'survey', 'sweet', 'swim', 320 | 'swing', 'switch', 'system', 'table', 'tackle', 'tale', 'talk', 'tank', 'tap', 'target', 321 | 'task', 'taste', 'tax', 'tea', 'teach', 'team', 'tear', 'tell', 'tennis', 'term', 322 | 'test', 'text', 'thanks', 'theme', 'theory', 'thing', 'throat', 'ticket', 'tie', 'till', 323 | 'time', 'tip', 'title', 'today', 'toe', 'tone', 'tongue', 'tool', 'tooth', 'top', 324 | 'topic', 'total', 'touch', 'tough', 'tour', 'towel', 'tower', 'town', 'track', 'trade', 325 | 'train', 'trash', 'travel', 'treat', 'tree', 'trick', 'trip', 'truck', 'trust', 'truth', 326 | 'try', 'tune', 'turn', 'twist', 'two', 'type', 'uncle', 'union', 'unique', 'unit', 327 | 'upper', 'use', 'user', 'usual', 'value', 'vast', 'video', 'view', 'virus', 'visit', 328 | 'visual', 'voice', 'volume', 'wait', 'wake', 'walk', 'wall', 'war', 'wash', 'watch', 329 | 'water', 'wave', 'way', 'wealth', 'wear', 'web', 'week', 'weight', 'weird', 'west', 330 | 'wheel', 'while', 'white', 'whole', 'wife', 'will', 'win', 'wind', 'window', 'wine', 331 | 'wing', 'winner', 'winter', 'wish', 'woman', 'wonder', 'wood', 'word', 'work', 'worker', 332 | 'world', 'worry', 'worth', 'wrap', 'writer', 'yard', 'year', 'yellow', 'you', 'young', 333 | 'youth', 'zone'] --------------------------------------------------------------------------------