def create_service_principal(name=None, secret=None, years=1): '''create a service principal you can use with login command :param str name: an unique uri. If missing, the command will generate one. :param str secret: the secret used to login. If missing, command will generate one. :param str years: Years the secret will be valid. ''' start_date = datetime.datetime.now() app_display_name = 'azure-cli-' + start_date.strftime('%Y-%m-%d-%H-%M-%S') if name is None: name = 'http://' + app_display_name key_id = str(uuid.uuid4()) end_date = start_date + relativedelta(years=years) secret = secret or str(uuid.uuid4()) app_cred = PasswordCredential(start_date, end_date, key_id, secret) app_create_param = ApplicationCreateParameters(False, app_display_name, 'http://'+app_display_name, [name], password_credentials=[app_cred]) profile = Profile() cred, _, tenant = profile.get_login_credentials(for_graph_client=True) client = GraphRbacManagementClient(cred, tenant) #pylint: disable=no-member aad_application = client.applications.create(app_create_param) aad_sp = client.service_principals.create(aad_application.app_id, True) _build_output_content(name, aad_sp.object_id, secret, tenant)
def test_get_login_credentials(self, mock_get_token, mock_read_cred_file): some_token_type = 'Bearer' mock_read_cred_file.return_value = json.dumps([Test_Profile.token_entry1]) mock_get_token.return_value = (some_token_type, Test_Profile.raw_token1) #setup storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) #action cred, subscription_id, _ = profile.get_login_credentials() #verify self.assertEqual(subscription_id, '1') #verify the cred._tokenRetriever is a working lambda token_type, token = cred._token_retriever() self.assertEqual(token, self.raw_token1) self.assertEqual(some_token_type, token_type) self.assertEqual(mock_read_cred_file.call_count, 1) mock_get_token.assert_called_once_with(mock.ANY, self.user1, self.tenant_id, 'https://management.core.windows.net/') self.assertEqual(mock_get_token.call_count, 1)
def _graph_client_factory(**_): from azure.cli._profile import Profile profile = Profile() cred, _, tenant_id = profile.get_login_credentials(True) client = GraphRbacManagementClient(cred, tenant_id) configure_common_settings(client) return client
def create_service_principal(name=None, secret=None, years=1): '''create a service principal you can use with login command :param str name: an unique uri. If missing, the command will generate one. :param str secret: the secret used to login. If missing, command will generate one. :param str years: Years the secret will be valid. ''' start_date = datetime.datetime.now() app_display_name = 'azure-cli-' + start_date.strftime('%Y-%m-%d-%H-%M-%S') if name is None: name = 'http://' + app_display_name key_id = str(uuid.uuid4()) end_date = start_date + relativedelta(years=years) secret = secret or str(uuid.uuid4()) app_cred = PasswordCredential(start_date, end_date, key_id, secret) app_create_param = ApplicationCreateParameters( False, app_display_name, 'http://' + app_display_name, [name], password_credentials=[app_cred]) profile = Profile() cred, _, tenant = profile.get_login_credentials(for_graph_client=True) client = GraphRbacManagementClient(cred, tenant) #pylint: disable=no-member aad_application = client.applications.create(app_create_param) aad_sp = client.service_principals.create(aad_application.app_id, True) _build_output_content(name, aad_sp.object_id, secret, tenant)
def _object_id_args_helper(object_id, spn, upn): if not object_id: from azure.cli._profile import Profile profile = Profile() cred, _, tenant_id = profile.get_login_credentials(for_graph_client=True) graph_client = GraphRbacManagementClient(cred, tenant_id) object_id = _get_object_id(graph_client, spn=spn, upn=upn) if not object_id: raise CLIError('Unable to get object id from principal name.') return object_id
def create_keyvault(client, resource_group_name, vault_name, location, #pylint:disable=too-many-arguments sku=SkuName.standard.value, enabled_for_deployment=None, enabled_for_disk_encryption=None, enabled_for_template_deployment=None, no_self_perms=False, tags=None): from azure.cli._profile import Profile profile = Profile() cred, _, tenant_id = profile.get_login_credentials(for_graph_client=True) graph_client = GraphRbacManagementClient(cred, tenant_id) subscription = profile.get_default_subscription() if no_self_perms: access_policies = [] else: # TODO Use the enums instead of strings when new keyvault SDK is released # https://github.com/Azure/azure-sdk-for-python/blob/dev/azure-mgmt-keyvault/ # azure/mgmt/keyvault/models/key_vault_management_client_enums.py permissions = Permissions(keys=['get', 'create', 'delete', 'list', 'update', 'import', 'backup', 'restore'], secrets=['all']) object_id = _get_current_user_object_id(graph_client) if not object_id: object_id = _get_object_id(graph_client, subscription=subscription) if not object_id: raise CLIError('Cannot create vault.\n' 'Unable to query active directory for information '\ 'about the current user.\n' 'You may try the --no-self-perms flag to create a vault'\ ' without permissions.') access_policies = [AccessPolicyEntry(tenant_id=tenant_id, object_id=object_id, permissions=permissions)] properties = VaultProperties(tenant_id=tenant_id, sku=Sku(name=sku, family='A'), access_policies=access_policies, vault_uri=None, enabled_for_deployment=enabled_for_deployment, enabled_for_disk_encryption=enabled_for_disk_encryption, enabled_for_template_deployment=enabled_for_template_deployment) parameters = VaultCreateOrUpdateParameters(location=location, tags=tags, properties=properties) return client.create_or_update(resource_group_name=resource_group_name, vault_name=vault_name, parameters=parameters)
def _mock_get_mgmt_service_client(client_type, subscription_bound=True): # version of _get_mgmt_service_client to use when recording or playing tests profile = Profile() cred, subscription_id, _ = profile.get_login_credentials() if subscription_bound: client = client_type(cred, subscription_id) else: client = client_type(cred) _debug.allow_debug_connection(client) client.config.add_user_agent("AZURECLI/TEST/{}".format(cli.__version__)) return (client, subscription_id)
def test_get_current_account_user(self, mock_read_cred_file): #setup mock_read_cred_file.return_value = json.dumps([Test_Profile.token_entry1]) storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) #action user = profile.get_current_account_user() #verify self.assertEqual(user, self.user1)
def test_get_login_credentials_for_graph_client(self, mock_get_token, mock_read_cred_file): some_token_type = 'Bearer' mock_read_cred_file.return_value = json.dumps([Test_Profile.token_entry1]) mock_get_token.return_value = (some_token_type, Test_Profile.raw_token1) #setup storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) #action cred, _, tenant_id = profile.get_login_credentials(for_graph_client=True) _, _ = cred._token_retriever() #verify mock_get_token.assert_called_once_with(mock.ANY, self.user1, self.tenant_id, 'https://graph.windows.net/') self.assertEqual(tenant_id, self.tenant_id)
def login(username=None, password=None, service_principal=None, tenant=None): '''Log in to an Azure subscription using Active Directory Organization Id''' interactive = False if username: if not password: import getpass password = getpass.getpass('Password: ') else: interactive = True profile = Profile() try: subscriptions = profile.find_subscriptions_on_login( interactive, username, password, service_principal, tenant) except AdalError as err: raise CLIError(err) return list(subscriptions)
def reset_service_principal_credential(name, secret=None, years=1): '''reset credential, on expiration or you forget it. :param str name: the uri representing the name of the service principal :param str secret: the secret used to login. If missing, command will generate one. :param str years: Years the secret will be valid. ''' profile = Profile() cred, _, tenant = profile.get_login_credentials(for_graph_client=True) client = GraphRbacManagementClient(cred, tenant) #pylint: disable=no-member #look for the existing application query_exp = 'identifierUris/any(x:x eq \'{}\')'.format(name) aad_apps = list(client.applications.list(filter=query_exp)) if not aad_apps: raise CLIError( 'can\'t find a graph application matching \'{}\''.format(name)) #no need to check 2+ matches, as app id uri is unique app = aad_apps[0] #look for the existing service principal query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name) aad_sps = list(client.service_principals.list(filter=query_exp)) if not aad_sps: raise CLIError( 'can\'t find an service principal matching \'{}\''.format(name)) sp_object_id = aad_sps[0].object_id #build a new password credential and patch it secret = secret or str(uuid.uuid4()) start_date = datetime.datetime.now() end_date = start_date + relativedelta(years=years) key_id = str(uuid.uuid4()) app_cred = PasswordCredential(start_date, end_date, key_id, secret) app_create_param = ApplicationUpdateParameters( password_credentials=[app_cred]) client.applications.patch(app.object_id, app_create_param) _build_output_content(name, sp_object_id, secret, tenant)
def test_update_add_two_different_subscriptions(self): storage_mock = {'subscriptions': None} profile = Profile(storage_mock) #add the first and verify consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(len(storage_mock['subscriptions']), 1) subscription1 = storage_mock['subscriptions'][0] self.assertEqual( subscription1, { 'environmentName': 'AzureCloud', 'id': '1', 'name': self.display_name1, 'state': self.state1, 'user': { 'name': self.user1, 'type': 'user' }, 'isDefault': True, 'tenantId': self.tenant_id }) #add the second and verify consolidated = Profile._normalize_properties(self.user2, [self.subscription2], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(len(storage_mock['subscriptions']), 2) subscription2 = storage_mock['subscriptions'][1] self.assertEqual( subscription2, { 'environmentName': 'AzureCloud', 'id': '2', 'name': self.display_name2, 'state': self.state2, 'user': { 'name': self.user2, 'type': 'user' }, 'isDefault': True, 'tenantId': self.tenant_id }) #verify the old one stays, but no longer active self.assertEqual(storage_mock['subscriptions'][0]['name'], subscription1['name']) self.assertFalse(storage_mock['subscriptions'][0]['isDefault'])
def test_load_cached_tokens(self, mock_read_file): mock_read_file.return_value = json.dumps([Test_Profile.token_entry1]) profile = Profile() cache = profile._creds_cache.adal_token_cache matched = cache.find({ "_authority": "https://login.microsoftonline.com/common", "_clientId": "04b07795-8ddb-461a-bbee-02f9e1bf7b46", "userId": self.user1 }) self.assertEqual(len(matched), 1) self.assertEqual(matched[0]['accessToken'], self.raw_token1)
def test_set_active_subscription(self): storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) consolidated = profile._normalize_properties(self.user2, [self.subscription2], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) subscription1 = storage_mock['subscriptions'][0] subscription2 = storage_mock['subscriptions'][1] self.assertTrue(subscription2['isDefault']) profile.set_active_subscription(subscription1['id']) self.assertFalse(subscription2['isDefault']) self.assertTrue(subscription1['isDefault'])
def test_get_login_credentials(self, mock_get_token, mock_read_cred_file): some_token_type = 'Bearer' mock_read_cred_file.return_value = json.dumps( [Test_Profile.token_entry1]) mock_get_token.return_value = (some_token_type, Test_Profile.raw_token1) #setup storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) #action cred, subscription_id, _ = profile.get_login_credentials() #verify self.assertEqual(subscription_id, '1') #verify the cred._tokenRetriever is a working lambda token_type, token = cred._token_retriever() self.assertEqual(token, self.raw_token1) self.assertEqual(some_token_type, token_type) self.assertEqual(mock_read_cred_file.call_count, 1) mock_get_token.assert_called_once_with( mock.ANY, self.user1, self.tenant_id, 'https://management.core.windows.net/') self.assertEqual(mock_get_token.call_count, 1)
def reset_service_principal_credential(name, secret=None, years=1): '''reset credential, on expiration or you forget it. :param str name: the uri representing the name of the service principal :param str secret: the secret used to login. If missing, command will generate one. :param str years: Years the secret will be valid. ''' profile = Profile() cred, _, tenant = profile.get_login_credentials(for_graph_client=True) client = GraphRbacManagementClient(cred, tenant) #pylint: disable=no-member #look for the existing application query_exp = 'identifierUris/any(x:x eq \'{}\')'.format(name) aad_apps = list(client.applications.list(filter=query_exp)) if not aad_apps: raise CLIError('can\'t find a graph application matching \'{}\''.format(name)) #no need to check 2+ matches, as app id uri is unique app = aad_apps[0] #look for the existing service principal query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name) aad_sps = list(client.service_principals.list(filter=query_exp)) if not aad_sps: raise CLIError('can\'t find an service principal matching \'{}\''.format(name)) sp_object_id = aad_sps[0].object_id #build a new password credential and patch it secret = secret or str(uuid.uuid4()) start_date = datetime.datetime.now() end_date = start_date + relativedelta(years=years) key_id = str(uuid.uuid4()) app_cred = PasswordCredential(start_date, end_date, key_id, secret) app_create_param = ApplicationUpdateParameters(password_credentials=[app_cred]) client.applications.patch(app.object_id, app_create_param) _build_output_content(name, sp_object_id, secret, tenant)
def test_update_add_two_different_subscriptions(self): storage_mock = {'subscriptions': None} profile = Profile(storage_mock) #add the first and verify consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(len(storage_mock['subscriptions']), 1) subscription1 = storage_mock['subscriptions'][0] self.assertEqual(subscription1, { 'environmentName': 'AzureCloud', 'id': '1', 'name': self.display_name1, 'state': self.state1, 'user': { 'name': self.user1, 'type': 'user' }, 'isDefault': True, 'tenantId': self.tenant_id }) #add the second and verify consolidated = Profile._normalize_properties(self.user2, [self.subscription2], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(len(storage_mock['subscriptions']), 2) subscription2 = storage_mock['subscriptions'][1] self.assertEqual(subscription2, { 'environmentName': 'AzureCloud', 'id': '2', 'name': self.display_name2, 'state': self.state2, 'user': { 'name': self.user2, 'type': 'user' }, 'isDefault': True, 'tenantId': self.tenant_id }) #verify the old one stays, but no longer active self.assertEqual(storage_mock['subscriptions'][0]['name'], subscription1['name']) self.assertFalse(storage_mock['subscriptions'][0]['isDefault'])
def test_normalize(self): consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) expected = { 'environmentName': 'AzureCloud', 'id': '1', 'name': self.display_name1, 'state': self.state1, 'user': { 'name': self.user1, 'type': 'user' }, 'isDefault': False, 'tenantId': self.tenant_id } self.assertEqual(expected, consolidated[0])
def test_update_with_same_subscription_added_twice(self): storage_mock = {'subscriptions': None} profile = Profile(storage_mock) #add one twice and verify we will have one but with new token consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) new_subscription1 = SubscriptionStub(self.id1, self.display_name1, self.state1, self.tenant_id) consolidated = Profile._normalize_properties(self.user1, [new_subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(len(storage_mock['subscriptions']), 1) self.assertTrue(storage_mock['subscriptions'][0]['isDefault'])
def test_logout_all(self, mock_delete_cred_file): #setup storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) consolidated2 = Profile._normalize_properties(self.user2, [self.subscription2], False, ENV_DEFAULT) profile._set_subscriptions(consolidated + consolidated2) self.assertEqual(2, len(storage_mock['subscriptions'])) #action profile.logout_all() #verify self.assertEqual(0, len(storage_mock['subscriptions'])) self.assertEqual(mock_delete_cred_file.call_count, 1)
def test_normalize(self): consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) expected = { 'environmentName': 'AzureCloud', 'id': '1', 'name': self.display_name1, 'state': self.state1, 'user': { 'name':self.user1, 'type':'user' }, 'isDefault': False, 'tenantId': self.tenant_id } self.assertEqual(expected, consolidated[0])
def test_logout(self, mock_persist_creds, mock_read_cred_file): #setup mock_read_cred_file.return_value = json.dumps( [Test_Profile.token_entry1]) storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(1, len(storage_mock['subscriptions'])) #action profile.logout(self.user1) #verify self.assertEqual(0, len(storage_mock['subscriptions'])) self.assertEqual(mock_read_cred_file.call_count, 1) self.assertEqual(mock_persist_creds.call_count, 1)
def test_get_current_account_user(self, mock_read_cred_file): #setup mock_read_cred_file.return_value = json.dumps( [Test_Profile.token_entry1]) storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) #action user = profile.get_current_account_user() #verify self.assertEqual(user, self.user1)
def test_logout(self, mock_persist_creds, mock_read_cred_file): #setup mock_read_cred_file.return_value = json.dumps([Test_Profile.token_entry1]) storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) self.assertEqual(1, len(storage_mock['subscriptions'])) #action profile.logout(self.user1) #verify self.assertEqual(0, len(storage_mock['subscriptions'])) self.assertEqual(mock_read_cred_file.call_count, 1) self.assertEqual(mock_persist_creds.call_count, 1)
def test_get_login_credentials_for_graph_client(self, mock_get_token, mock_read_cred_file): some_token_type = 'Bearer' mock_read_cred_file.return_value = json.dumps( [Test_Profile.token_entry1]) mock_get_token.return_value = (some_token_type, Test_Profile.raw_token1) #setup storage_mock = {'subscriptions': None} profile = Profile(storage_mock) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False, ENV_DEFAULT) profile._set_subscriptions(consolidated) #action cred, _, tenant_id = profile.get_login_credentials( for_graph_client=True) _, _ = cred._token_retriever() #verify mock_get_token.assert_called_once_with(mock.ANY, self.user1, self.tenant_id, 'https://graph.windows.net/') self.assertEqual(tenant_id, self.tenant_id)
def set_active_subscription(subscription_name_or_id): '''Set the current subscription''' if not id: raise CLIError('Please provide subscription id or unique name.') profile = Profile() profile.set_active_subscription(subscription_name_or_id)
def account_clear(): '''Clear all stored subscriptions. To clear individual, use \'logout\'''' profile = Profile() profile.logout_all()
def logout(username=None): '''Log out from Azure subscription using Active Directory''' profile = Profile() if not username: username = profile.get_current_account_user() profile.logout(username)
def load_subscriptions(): profile = Profile() subscriptions = profile.load_cached_subscriptions() return subscriptions
def test_create_token_cache(self, mock_read_file): profile = Profile() cache = profile._creds_cache.adal_token_cache self.assertFalse(cache.read_items()) self.assertTrue(mock_read_file.called)