From dabf5e5cf531006af0219484f3a2db9e5280cde1 Mon Sep 17 00:00:00 2001 From: "Ruijun Hu (Wicresoft North America Ltd)" Date: Thu, 14 May 2020 01:50:53 +0000 Subject: [PATCH 1/4] update azure-keyvault to track 2 --- example.py | 80 ++++++++++++++++++++++-------------------------- requirements.txt | 14 +++++---- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/example.py b/example.py index 62fcbee..91bcc99 100644 --- a/example.py +++ b/example.py @@ -7,13 +7,14 @@ from haikunator import Haikunator from azure.common.credentials import ServicePrincipalCredentials +from azure.identity import ClientSecretCredential from azure.mgmt.resource import ResourceManagementClient from azure.mgmt.compute import ComputeManagementClient from azure.mgmt.network import NetworkManagementClient from azure.mgmt.keyvault import KeyVaultManagementClient -from azure.keyvault import KeyVaultClient -from azure.keyvault.models import * +from azure.keyvault.certificates import LifetimeAction, CertificateClient, CertificatePolicy, CertificatePolicyAction +from azure.keyvault.secrets import SecretClient from azure.graphrbac import GraphRbacManagementClient HAIKUNATOR = Haikunator() @@ -35,34 +36,25 @@ # - Is pre-configured in the Portal when you choose "Generate" in the Certificates tab # - You get when you use the CLI 2.0: az keyvault certificate get-default-policy DEFAULT_POLICY = CertificatePolicy( - key_properties=KeyProperties( - exportable=True, - key_type='RSA', - key_size=2048, - reuse_key=True - ), - secret_properties=SecretProperties(content_type='application/x-pkcs12'), - issuer_parameters=IssuerParameters(name='Self'), - x509_certificate_properties=X509CertificateProperties( - subject='CN=CLIGetDefaultPolicy', - validity_in_months=12, - key_usage=[ - "cRLSign", - "dataEncipherment", - "digitalSignature", - "keyEncipherment", - "keyAgreement", - "keyCertSign" - ] - ), - lifetime_actions=[{ - "action": Action( - action_type="AutoRenew" - ), - "trigger": Trigger( - days_before_expiry=90 - ) - }] + 'Self', + exportable=True, + key_type='RSA', + key_size=2048, + reuse_key=True, + content_type='application/x-pkcs12', + subject='CN=CLIGetDefaultPolicy', + validity_in_months=12, + key_usage=[ + "cRLSign", + "dataEncipherment", + "digitalSignature", + "keyEncipherment", + "keyAgreement", + "keyCertSign" + ], + lifetime_actions=[ + LifetimeAction(action=CertificatePolicyAction.auto_renew, days_before_expiry=90) + ] ) # Network @@ -107,13 +99,16 @@ def run_example(): network_client = NetworkManagementClient(credentials, subscription_id) kv_mgmt_client = KeyVaultManagementClient(credentials, subscription_id) - kv_credentials = ServicePrincipalCredentials( + kv_credentials = ClientSecretCredential( client_id=os.environ['AZURE_CLIENT_ID'], - secret=os.environ['AZURE_CLIENT_SECRET'], - tenant=os.environ['AZURE_TENANT_ID'], + client_secret=os.environ['AZURE_CLIENT_SECRET'], + tenant_id=os.environ['AZURE_TENANT_ID'], resource="https://vault.azure.net" ) - kv_client = KeyVaultClient(kv_credentials) + cert_client = CertificateClient( + "https://{}.vault.azure.net".format(KV_NAME), + kv_credentials + ) # Create Resource group print('\nCreate Resource Group') @@ -162,16 +157,12 @@ def run_example(): # Ask KeyVault to create a Certificate certificate_name = "cert1" print('\nCreate Key Vault Certificate') - kv_client.create_certificate( - vault.properties.vault_uri, + cert_client.begin_create_certificate( certificate_name, - certificate_policy=DEFAULT_POLICY + policy=DEFAULT_POLICY ) while True: - check = kv_client.get_certificate_operation( - vault.properties.vault_uri, - certificate_name - ) + check = cert_client.get_certificate_operation(certificate_name) if check.status != 'inProgress': break try: @@ -183,8 +174,11 @@ def run_example(): print_item(check) print('\nGet Key Vault created certificate as a secret') - certificate_as_secret = kv_client.get_secret( - vault.properties.vault_uri, + secret_client = SecretClient( + "https://{}.vault.azure.net".format(KV_NAME), + kv_credentials + ) + certificate_as_secret = secret_client.get_secret( certificate_name, "" # Latest version ) diff --git a/requirements.txt b/requirements.txt index 3dbcb63..7f757eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,9 @@ -azure-mgmt-resource>=2.0.0 -azure-mgmt-compute>=4.0.1 -azure-mgmt-network>=2.1.0 -azure-mgmt-keyvault>=1.1.0 -azure-keyvault>=1.1.0 -azure-graphrbac>=0.40.0 +azure-mgmt-resource==2.0.0 +azure-mgmt-compute==4.0.1 +azure-mgmt-network==2.1.0 +azure-mgmt-keyvault==1.1.0 +azure-keyvault-certificates==4.1.0 +azure-keyvault-secrets==4.1.0 +azure-identity==1.3.1 +azure-graphrbac==0.40.0 haikunator \ No newline at end of file From de6662c67bbc021a1aa9e04d78d7288d4664055a Mon Sep 17 00:00:00 2001 From: "Ruijun Hu (Wicresoft North America Ltd)" Date: Thu, 13 Aug 2020 15:36:24 +0800 Subject: [PATCH 2/4] update all content to track 2 --- README.md | 131 ++++++++++++++++++++++------------------------- example.py | 66 ++++++++---------------- requirements.txt | 10 ++-- 3 files changed, 85 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index d08e25f..2521a1b 100644 --- a/README.md +++ b/README.md @@ -29,20 +29,19 @@ or [the portal](https://azure.microsoft.com/documentation/articles/resource-grou 1. If you don't already have it, [install Python](https://www.python.org/downloads/). - This sample (and the SDK) is compatible with Python 2.7, 3.4, 3.5, 3.6 and 3.7. + This sample (and the SDK) is compatible with Python 2.7, and 3.5+. 2. We recommend that you use a [virtual environment](https://docs.python.org/3/tutorial/venv.html) to run this example, but it's not required. Install and initialize the virtual environment with the "venv" module on Python 3 (you must install [virtualenv](https://pypi.python.org/pypi/virtualenv) for Python 2.7): ``` - python -m venv mytestenv # Might be "python3" or "py -3.6" depending on your Python installation - cd mytestenv - source bin/activate # Linux shell (Bash, ZSH, etc.) only - ./scripts/activate # PowerShell only - ./scripts/activate.bat # Windows CMD only + python -m venv env # Might be "python3" or "py -3.6" depending on your Python installation + source env/bin/activate # Linux shell (Bash, ZSH, etc.) only + env/scripts/activate # PowerShell only + env/scripts/activate.bat # Windows CMD only ``` - + 1. Clone the repository. ``` @@ -61,6 +60,7 @@ or [the portal](https://azure.microsoft.com/documentation/articles/resource-grou ``` export AZURE_TENANT_ID={your tenant id} export AZURE_CLIENT_ID={your client id} + export AZURE_CLIENT_OBJECT_ID={your client object id} export AZURE_CLIENT_SECRET={your client secret} export AZURE_SUBSCRIPTION_ID={your subscription id} ``` @@ -92,30 +92,30 @@ For details about creation of these components, you can refer to the generic sam ### Creating a KeyVault account enabled for deployment ```python - vault = kv_mgmt_client.vaults.create_or_update( - GROUP_NAME, - KV_NAME, - { - 'location': LOCATION, - 'properties': { - 'sku': { - 'name': 'standard' - }, +vault = kv_mgmt_client.vaults.begin_create_or_update( + GROUP_NAME, + KV_NAME, + { + 'location': LOCATION, + 'properties': { + 'sku': { + 'name': 'standard' + }, + 'tenant_id': os.environ['AZURE_TENANT_ID'], + 'access_policies': [{ 'tenant_id': os.environ['AZURE_TENANT_ID'], - 'access_policies': [{ - 'tenant_id': os.environ['AZURE_TENANT_ID'], - 'object_id': sp_object_id, - 'permissions': { - # Only "certificates" and "secrets" are needed for this sample - 'certificates': ['all'], - 'secrets': ['all'] - } - }], - # Critical to allow the VM to download certificates later - 'enabled_for_deployment': True - } + 'object_id': sp_object_id, + 'permissions': { + # Only "certificates" and "secrets" are needed for this sample + 'certificates': ['all'], + 'secrets': ['all'] + } + }], + # Critical to allow the VM to download certificates later + 'enabled_for_deployment': True } - ) + } +) ``` You can also found different example on how to create a Key Vault account: @@ -126,49 +126,39 @@ You can also found different example on how to create a Key Vault account: > In order to execute this sample, your Key Vault account MUST have the "enabled-for-deployment" special permission. The EnabledForDeployment flag explicitly gives Azure (Microsoft.Compute resource provider) permission to use the certificates stored as secrets for this deployment. -> Note that access policy takes an *object_id*, not a client_id as parameter. This samples also provide a quick way to convert a Service Principal client_id to an object_id using the `azure-graphrbac` client. +> Note that access policy takes an *object_id*, not a client_id as parameter. ### Ask Key Vault to create a certificate for you ```python - kv_client.create_certificate( - vault.properties.vault_uri, - certificate_name, - certificate_policy=DEFAULT_POLICY - ) +cert_client.begin_create_certificate( + certificate_name, + certificate_policy=DEFAULT_POLICY +) ``` An example of `DEFAULT_POLICY` is described in the sample file: ```python DEFAULT_POLICY = CertificatePolicy( - key_properties=KeyProperties( - exportable=True, - key_type='RSA', - key_size=2048, - reuse_key=True - ), - secret_properties=SecretProperties(content_type='application/x-pkcs12'), - issuer_parameters=IssuerParameters(name='Self'), - x509_certificate_properties=X509CertificateProperties( - subject='CN=CLIGetDefaultPolicy', - validity_in_months=12, - key_usage=[ - "cRLSign", - "dataEncipherment", - "digitalSignature", - "keyEncipherment", - "keyAgreement", - "keyCertSign" - ] - ), - lifetime_actions=[{ - "action": Action( - action_type="AutoRenew" - ), - "trigger": Trigger( - days_before_expiry=90 - ) - }] + 'Self', + exportable=True, + key_type='RSA', + key_size=2048, + reuse_key=True, + content_type='application/x-pkcs12', + subject='CN=CLIGetDefaultPolicy', + validity_in_months=12, + key_usage=[ + "cRLSign", + "dataEncipherment", + "digitalSignature", + "keyEncipherment", + "keyAgreement", + "keyCertSign" + ], + lifetime_actions=[ + LifetimeAction(action=CertificatePolicyAction.auto_renew, days_before_expiry=90) + ] ) ``` @@ -184,14 +174,13 @@ This is the same policy that: First, get your certificate as a Secret object: ```python - certificate_as_secret = kv_client.get_secret( - vault.properties.vault_uri, - certificate_name, - "" # Latest version - ) +certificate_as_secret = secret_client.get_secret( + certificate_name, + "" # Latest version +) ``` -During the creation of the VM, use the `secrets` atribute to assign your certificate:. +During the creation of the VM, use the `secrets` attribute to assign your certificate:. ```python params_create = { @@ -215,7 +204,7 @@ params_create = { } } -vm_poller = compute_client.virtual_machines.create_or_update( +vm_poller = compute_client.virtual_machines.begin_create_or_update( GROUP_NAME, VM_NAME, params_create, @@ -228,4 +217,4 @@ vm_result = vm_poller.result() - https://azure.microsoft.com/services/key-vault/ - https://github.com/Azure/azure-sdk-for-python -- https://docs.microsoft.com/python/api/overview/azure/key-vault +- https://docs.microsoft.com/en-us/azure/key-vault/ diff --git a/example.py b/example.py index 91bcc99..e2a4b3e 100644 --- a/example.py +++ b/example.py @@ -6,7 +6,6 @@ from haikunator import Haikunator -from azure.common.credentials import ServicePrincipalCredentials from azure.identity import ClientSecretCredential from azure.mgmt.resource import ResourceManagementClient @@ -15,7 +14,6 @@ from azure.mgmt.keyvault import KeyVaultManagementClient from azure.keyvault.certificates import LifetimeAction, CertificateClient, CertificatePolicy, CertificatePolicyAction from azure.keyvault.secrets import SecretClient -from azure.graphrbac import GraphRbacManagementClient HAIKUNATOR = Haikunator() @@ -24,7 +22,7 @@ # Resource -LOCATION = 'westus' +LOCATION = 'westus2' GROUP_NAME = 'azure-kv-vm-certificate-sample-group' # KeyVault @@ -78,6 +76,7 @@ # # AZURE_TENANT_ID: with your Azure Active Directory tenant id or domain # AZURE_CLIENT_ID: with your Azure Active Directory Application Client ID +# AZURE_CLIENT_OBJECT_ID: with your Azure Active Directory Application Object ID # AZURE_CLIENT_SECRET: with your Azure Active Directory Application Secret # AZURE_SUBSCRIPTION_ID: with your Azure Subscription Id # @@ -89,25 +88,19 @@ def run_example(): subscription_id = os.environ.get( 'AZURE_SUBSCRIPTION_ID', '11111111-1111-1111-1111-111111111111') # your Azure Subscription Id - credentials = ServicePrincipalCredentials( - client_id=os.environ['AZURE_CLIENT_ID'], - secret=os.environ['AZURE_CLIENT_SECRET'], - tenant=os.environ['AZURE_TENANT_ID'] - ) - resource_client = ResourceManagementClient(credentials, subscription_id) - compute_client = ComputeManagementClient(credentials, subscription_id) - network_client = NetworkManagementClient(credentials, subscription_id) - kv_mgmt_client = KeyVaultManagementClient(credentials, subscription_id) - - kv_credentials = ClientSecretCredential( + credential = ClientSecretCredential( client_id=os.environ['AZURE_CLIENT_ID'], client_secret=os.environ['AZURE_CLIENT_SECRET'], - tenant_id=os.environ['AZURE_TENANT_ID'], - resource="https://vault.azure.net" + tenant_id=os.environ['AZURE_TENANT_ID'] ) + resource_client = ResourceManagementClient(credential, subscription_id) + compute_client = ComputeManagementClient(credential, subscription_id) + network_client = NetworkManagementClient(credential, subscription_id) + kv_mgmt_client = KeyVaultManagementClient(credential, subscription_id) + cert_client = CertificateClient( "https://{}.vault.azure.net".format(KV_NAME), - kv_credentials + credential ) # Create Resource group @@ -120,11 +113,13 @@ def run_example(): # Resolve the client_id as object_id for KeyVault access policy. # If you already know your object_id, you can skip this part - sp_object_id = resolve_service_principal(os.environ['AZURE_CLIENT_ID']) + sp_object_id = os.environ.get( + 'AZURE_CLIENT_OBJECT_ID', + '11111111-1111-1111-1111-111111111111') # your service principal's object id # Create Key Vault account print('\nCreate Key Vault account') - async_vault_poller = kv_mgmt_client.vaults.create_or_update( + async_vault_poller = kv_mgmt_client.vaults.begin_create_or_update( GROUP_NAME, KV_NAME, { @@ -176,7 +171,7 @@ def run_example(): print('\nGet Key Vault created certificate as a secret') secret_client = SecretClient( "https://{}.vault.azure.net".format(KV_NAME), - kv_credentials + credential ) certificate_as_secret = secret_client.get_secret( certificate_name, @@ -215,7 +210,7 @@ def run_example(): } print("\nCreate VM") - vm_poller = compute_client.virtual_machines.create_or_update( + vm_poller = compute_client.virtual_machines.begin_create_or_update( GROUP_NAME, VM_NAME, params_create, @@ -243,7 +238,7 @@ def run_example(): # Delete Resource group and everything in it print('Delete Resource Group') - delete_async_operation = resource_client.resource_groups.delete(GROUP_NAME) + delete_async_operation = resource_client.resource_groups.begin_delete(GROUP_NAME) delete_async_operation.wait() print("\nDeleted: {}".format(GROUP_NAME)) @@ -265,27 +260,6 @@ def print_properties(props): print("\t\tProvisioning State: {}".format(props.provisioning_state)) print("\n\n") - -def resolve_service_principal(identifier): - """Get an object_id from a client_id. - """ - graphrbac_credentials = ServicePrincipalCredentials( - client_id=os.environ['AZURE_CLIENT_ID'], - secret=os.environ['AZURE_CLIENT_SECRET'], - tenant=os.environ['AZURE_TENANT_ID'], - resource="https://graph.windows.net" - ) - graphrbac_client = GraphRbacManagementClient( - graphrbac_credentials, - os.environ['AZURE_TENANT_ID'] - ) - - result = list(graphrbac_client.service_principals.list( - filter="servicePrincipalNames/any(c:c eq '{}')".format(identifier))) - if result: - return result[0].object_id - raise RuntimeError("Unable to get object_id from client_id") - ###### Network creation, not specific to MSI scenario ###### @@ -302,7 +276,7 @@ def create_virtual_network(network_client): 'address_prefix': '10.0.0.0/24', }], } - vnet_poller = network_client.virtual_networks.create_or_update( + vnet_poller = network_client.virtual_networks.begin_create_or_update( GROUP_NAME, VNET_NAME, params_create, @@ -323,7 +297,7 @@ def create_public_ip(network_client): 'location': LOCATION, 'public_ip_allocation_method': 'dynamic', } - pip_poller = network_client.public_ip_addresses.create_or_update( + pip_poller = network_client.public_ip_addresses.begin_create_or_update( GROUP_NAME, PUBLIC_IP_NAME, params_create, @@ -345,7 +319,7 @@ def create_network_interface(network_client, subnet, public_ip): } }] } - nic_poller = network_client.network_interfaces.create_or_update( + nic_poller = network_client.network_interfaces.begin_create_or_update( GROUP_NAME, NIC_NAME, params_create, diff --git a/requirements.txt b/requirements.txt index 7f757eb..c52dea7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ -azure-mgmt-resource==2.0.0 -azure-mgmt-compute==4.0.1 -azure-mgmt-network==2.1.0 -azure-mgmt-keyvault==1.1.0 +azure-mgmt-resource==15.0.0b1 +azure-mgmt-compute==17.0.0b1 +azure-mgmt-network==16.0.0b1 +azure-mgmt-keyvault==7.0.0b2 azure-keyvault-certificates==4.1.0 azure-keyvault-secrets==4.1.0 azure-identity==1.3.1 -azure-graphrbac==0.40.0 + haikunator \ No newline at end of file From f5df762a532b900e9af2d9ecf276f58c7e8771e3 Mon Sep 17 00:00:00 2001 From: "Ruijun Hu (Wicresoft North America Ltd)" Date: Mon, 28 Sep 2020 11:05:53 +0800 Subject: [PATCH 3/4] add .wait() for poller --- README.md | 7 ++++--- example.py | 3 ++- requirements.txt | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2521a1b..a54e953 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ vault = kv_mgmt_client.vaults.begin_create_or_update( ) ``` -You can also found different example on how to create a Key Vault account: +You can also find different example on how to create a Key Vault account: - From CLI 2.0: https://docs.microsoft.com/azure/key-vault/key-vault-manage-with-cli2 - From Python SDK: https://github.com/Azure-Samples/key-vault-python-manage @@ -131,10 +131,11 @@ You can also found different example on how to create a Key Vault account: ### Ask Key Vault to create a certificate for you ```python -cert_client.begin_create_certificate( +certificate_poller = cert_client.begin_create_certificate( certificate_name, - certificate_policy=DEFAULT_POLICY + policy=DEFAULT_POLICY ) +certificate_poller.wait() ``` An example of `DEFAULT_POLICY` is described in the sample file: diff --git a/example.py b/example.py index e2a4b3e..38be23f 100644 --- a/example.py +++ b/example.py @@ -152,10 +152,11 @@ def run_example(): # Ask KeyVault to create a Certificate certificate_name = "cert1" print('\nCreate Key Vault Certificate') - cert_client.begin_create_certificate( + certificate_poller = cert_client.begin_create_certificate( certificate_name, policy=DEFAULT_POLICY ) + certificate_poller.wait() while True: check = cert_client.get_certificate_operation(certificate_name) if check.status != 'inProgress': diff --git a/requirements.txt b/requirements.txt index c52dea7..8d67c31 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ azure-mgmt-resource==15.0.0b1 azure-mgmt-compute==17.0.0b1 azure-mgmt-network==16.0.0b1 -azure-mgmt-keyvault==7.0.0b2 -azure-keyvault-certificates==4.1.0 -azure-keyvault-secrets==4.1.0 -azure-identity==1.3.1 +azure-mgmt-keyvault==7.0.0b3 +azure-keyvault-certificates==4.2.0 +azure-keyvault-secrets==4.2.0 +azure-identity==1.4.0 haikunator \ No newline at end of file From f6c26c7413d6131c8466caaef0f6423c9e88f6f3 Mon Sep 17 00:00:00 2001 From: "Ruijun Hu (Wicresoft North America Ltd)" Date: Tue, 29 Sep 2020 10:30:32 +0800 Subject: [PATCH 4/4] fix py2, py3 compatibility --- example.py | 1 + requirements.txt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/example.py b/example.py index 38be23f..03743c4 100644 --- a/example.py +++ b/example.py @@ -5,6 +5,7 @@ import time from haikunator import Haikunator +from six.moves import input from azure.identity import ClientSecretCredential diff --git a/requirements.txt b/requirements.txt index 8d67c31..6d43f80 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,5 @@ azure-keyvault-certificates==4.2.0 azure-keyvault-secrets==4.2.0 azure-identity==1.4.0 -haikunator \ No newline at end of file +haikunator +six \ No newline at end of file