def test_get_raw_token(self, mock_get_token, mock_read_cred_file): some_token_type = 'Bearer' mock_read_cred_file.return_value = [Test_Profile.token_entry1] mock_get_token.return_value = (some_token_type, Test_Profile.raw_token1, Test_Profile.token_entry1) # setup storage_mock = {'subscriptions': None} profile = Profile(storage_mock, use_global_creds_cache=False) consolidated = Profile._normalize_properties(self.user1, [self.subscription1], False) profile._set_subscriptions(consolidated) # action creds, sub, tenant = profile.get_raw_token(resource='https://foo') # verify self.assertEqual(creds[0], self.token_entry1['tokenType']) self.assertEqual(creds[1], self.raw_token1) # the last in the tuple is the whole token entry which has several fields self.assertEqual(creds[2]['expiresOn'], self.token_entry1['expiresOn']) mock_get_token.assert_called_once_with(mock.ANY, self.user1, self.tenant_id, 'https://foo') self.assertEqual(mock_get_token.call_count, 1) self.assertEqual(sub, '1') self.assertEqual(tenant, self.tenant_id)
def login(username=None, password=None, service_principal=None, tenant=None, allow_no_subscriptions=False, msi=False, msi_port=DefaultStr(50342)): """Log in to access Azure subscriptions""" import os import re from adal.adal_error import AdalError import requests # quick argument usage check if (any([username, password, service_principal, tenant, allow_no_subscriptions]) and any([msi, not getattr(msi_port, 'is_default', None)])): raise CLIError("usage error: '--msi/--msi-port' are not applicable with other arguments") interactive = False profile = Profile() if in_cloud_console(): console_tokens = os.environ.get('AZURE_CONSOLE_TOKENS', None) if console_tokens: return profile.find_subscriptions_in_cloud_console(re.split(';|,', console_tokens)) logger.warning(_CLOUD_CONSOLE_WARNING_TEMPLATE, 'login') return if msi: return profile.find_subscriptions_in_vm_with_msi(msi_port) if username: if not password: try: password = prompt_pass('Password: '******'Please specify both username and password in non-interactive mode.') else: interactive = True try: subscriptions = profile.find_subscriptions_on_login( interactive, username, password, service_principal, tenant, allow_no_subscriptions=allow_no_subscriptions) except AdalError as err: # try polish unfriendly server errors if username: msg = str(err) suggestion = "For cross-check, try 'az login' to authenticate through browser." if ('ID3242:' in msg) or ('Server returned an unknown AccountType' in msg): raise CLIError("The user name might be invalid. " + suggestion) if 'Server returned error in RSTR - ErrorCode' in msg: raise CLIError("Logging in through command line is not supported. " + suggestion) raise CLIError(err) except requests.exceptions.ConnectionError as err: raise CLIError('Please ensure you have network connection. Error detail: ' + str(err)) all_subscriptions = list(subscriptions) for sub in all_subscriptions: sub['cloudName'] = sub.pop('environmentName', None) return all_subscriptions
def login(username=None, password=None, service_principal=None, tenant=None): '''Log in to access Azure subscriptions''' interactive = False if username: if not password: import getpass password = getpass.getpass('Password: '******'az login' to authenticate through browser" if ('ID3242:' in msg) or ('Server returned an unknown AccountType' in msg): raise CLIError("The user name might be invalid. " + suggestion) if 'Server returned error in RSTR - ErrorCode' in msg: raise CLIError("Logging in through command line is not supported. " + suggestion) raise CLIError(err) return list(subscriptions)
def _get_mgmt_service_client(client_type, subscription_bound=True, subscription_id=None, api_version=None, base_url_bound=True, resource=CLOUD.endpoints.active_directory_resource_id, **kwargs): logger.debug('Getting management service client client_type=%s', client_type.__name__) profile = Profile() cred, subscription_id, _ = profile.get_login_credentials(subscription_id=subscription_id, resource=resource) client_kwargs = {} if base_url_bound: client_kwargs = {'base_url': CLOUD.endpoints.resource_manager} if api_version: client_kwargs['api_version'] = api_version if kwargs: client_kwargs.update(kwargs) if subscription_bound: client = client_type(cred, subscription_id, **client_kwargs) else: client = client_type(cred, **client_kwargs) configure_common_settings(client) return (client, subscription_id)
def _get_mgmt_service_client(cli_ctx, client_type, subscription_bound=True, subscription_id=None, api_version=None, base_url_bound=True, resource=None, sdk_profile=None, **kwargs): from azure.cli.core._profile import Profile logger.debug('Getting management service client client_type=%s', client_type.__name__) resource = resource or cli_ctx.cloud.endpoints.active_directory_resource_id profile = Profile(cli_ctx=cli_ctx) cred, subscription_id, _ = profile.get_login_credentials(subscription_id=subscription_id, resource=resource) client_kwargs = {} if base_url_bound: client_kwargs = {'base_url': cli_ctx.cloud.endpoints.resource_manager} if api_version: client_kwargs['api_version'] = api_version if sdk_profile: client_kwargs['profile'] = sdk_profile if kwargs: client_kwargs.update(kwargs) if subscription_bound: client = client_type(cred, subscription_id, **client_kwargs) else: client = client_type(cred, **client_kwargs) configure_common_settings(cli_ctx, client) return client, subscription_id
def test_get_expanded_subscription_info_for_logged_in_service_principal(self, mock_auth_context): mock_auth_context.acquire_token_with_client_credentials.return_value = self.token_entry1 mock_arm_client = mock.MagicMock() mock_arm_client.subscriptions.list.return_value = [self.subscription1] finder = SubscriptionFinder(lambda _, _2: mock_auth_context, None, lambda _: mock_arm_client) storage_mock = {'subscriptions': []} profile = Profile(storage_mock, use_global_creds_cache=False) profile._management_resource_uri = 'https://management.core.windows.net/' profile.find_subscriptions_on_login(False, '1234', 'my-secret', True, self.tenant_id, False, finder) # action extended_info = profile.get_expanded_subscription_info() # assert self.assertEqual(self.id1.split('/')[-1], extended_info['subscriptionId']) self.assertEqual(self.display_name1, extended_info['subscriptionName']) self.assertEqual('1234', extended_info['client']) self.assertEqual('https://login.microsoftonline.com', extended_info['endpoints'].active_directory)
def test_create_account_without_subscriptions_thru_common_tenant(self, mock_auth_context): mock_auth_context.acquire_token.return_value = self.token_entry1 mock_auth_context.acquire_token_with_username_password.return_value = self.token_entry1 tenant_object = mock.MagicMock() tenant_object.id = "foo-bar" tenant_object.tenant_id = self.tenant_id mock_arm_client = mock.MagicMock() mock_arm_client.subscriptions.list.return_value = [] mock_arm_client.tenants.list.return_value = (x for x in [tenant_object]) finder = SubscriptionFinder(lambda _, _2: mock_auth_context, None, lambda _: mock_arm_client) storage_mock = {'subscriptions': []} profile = Profile(storage_mock, use_global_creds_cache=False) profile._management_resource_uri = 'https://management.core.windows.net/' # action result = profile.find_subscriptions_on_login(False, '1234', 'my-secret', False, None, allow_no_subscriptions=True, subscription_finder=finder) # assert self.assertEqual(1, len(result)) self.assertEqual(result[0]['id'], self.tenant_id) self.assertEqual(result[0]['state'], 'Enabled') self.assertEqual(result[0]['tenantId'], self.tenant_id) self.assertEqual(result[0]['name'], 'N/A(tenant level account)')
def batch_data_service_factory(cli_ctx, kwargs): import azure.batch.batch_service_client as batch import azure.batch.batch_auth as batchauth account_name = kwargs.pop('account_name', None) account_key = kwargs.pop('account_key', None) account_endpoint = kwargs.pop('account_endpoint', None) kwargs.pop('yes', None) credentials = None if not account_key: from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) # in order to use AAD auth in cloud shell mode, we will use mgmt AAD token # instead of Batch AAD token to auth if in_cloud_console(): resource = cli_ctx.cloud.endpoints.active_directory_resource_id else: resource = cli_ctx.cloud.endpoints.batch_resource_id credentials, _, _ = profile.get_login_credentials(resource=resource) else: credentials = batchauth.SharedKeyCredentials(account_name, account_key) if not (account_endpoint.startswith('https://') or account_endpoint.startswith('http://')): account_endpoint = 'https://' + account_endpoint return batch.BatchServiceClient(credentials, batch_url=account_endpoint.rstrip('/'))
def list_releases(target_name, target_resource_group): """ Lists all the release definitions that are deployed to a given Azure container service. :param target_name: Name of the target Azure container service instance. :type target_name: String :param target_resource_group: Name of Azure container service's resource group. :type target_resource_group: String """ profile = Profile() _, subscription_id, _ = profile.get_login_credentials() o_auth_token = _get_service_token() container_service_resource_id = CONTAINER_SERVICE_RESOURCE_URL.format(subscription_id=subscription_id, resource_group_name=target_resource_group, container_service_name=target_name) data = { 'acsResourceId': container_service_resource_id } list_releases_url = SERVICE_URL.format( subscription_id=subscription_id) + '/listReleases?api-version=' + API_VERSION headers = {} headers['Authorization'] = o_auth_token headers['Content-Type'] = 'application/json; charset=utf-8' headers['x-ms-client-request-id'] = str(uuid.uuid1()) req = requests.post(list_releases_url, data=json.dumps(data), headers=headers, timeout=600) while req.status_code == 202: # Long-running operation time.sleep(10) req = requests.get(BASE_URL + req.headers['Location'], headers=headers, timeout=600) if req.status_code != 200: raise CLIError( 'Server returned status code: ' + str(req.status_code) + '. Could not list releases: ' + req.text) json_request = req.json() return json_request
def test_get_login_credentials(self, mock_get_token, mock_read_cred_file): some_token_type = 'Bearer' mock_read_cred_file.return_value = [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 setup_continuous_delivery(self, cli_ctx, resource_group_name, name, repo_url, branch, git_token, slot, cd_app_type_details, cd_project_url, cd_create_account, location, test, private_repo_username, private_repo_password, webapp_list): """ This method sets up CD for an Azure Web App thru Team Services """ # Gather information about the Azure connection profile = Profile(cli_ctx=cli_ctx) subscription = profile.get_subscription() user = profile.get_current_account_user() cred, _, _ = profile.get_login_credentials(subscription_id=None) cd_manager = ContinuousDeliveryManager(self._update_progress) # Generate an Azure token with the VSTS resource app id auth_token = profile.get_access_token_for_resource(user, None, cd_manager.get_vsts_app_id()) cd_manager.set_repository_info(repo_url, branch, git_token, private_repo_username, private_repo_password) cd_manager.set_azure_web_info(resource_group_name, name, cred, subscription['id'], subscription['name'], subscription['tenantId'], location) vsts_cd_status = cd_manager.setup_continuous_delivery(slot, cd_app_type_details, cd_project_url, cd_create_account, auth_token, test, webapp_list) return vsts_cd_status
def login_account(cmd, client, resource_group_name, account_name, shared_key_auth=False, show=False): account = client.get(resource_group_name=resource_group_name, account_name=account_name) cmd.cli_ctx.config.set_value('batch', 'account', account.name) cmd.cli_ctx.config.set_value('batch', 'endpoint', 'https://{}/'.format(account.account_endpoint)) if shared_key_auth: keys = client.get_keys(resource_group_name=resource_group_name, account_name=account_name) cmd.cli_ctx.config.set_value('batch', 'auth_mode', 'shared_key') cmd.cli_ctx.config.set_value('batch', 'access_key', keys.primary) if show: return { 'account': account.name, 'endpoint': 'https://{}/'.format(account.account_endpoint), 'primaryKey': keys.primary, 'secondaryKey': keys.secondary } else: cmd.cli_ctx.config.set_value('batch', 'auth_mode', 'aad') if show: resource = cmd.cli_ctx.cloud.endpoints.batch_resource_id profile = Profile(cli_ctx=cmd.cli_ctx) creds, subscription, tenant = profile.get_raw_token(resource=resource) return { 'tokenType': creds[0], 'accessToken': creds[1], 'expiresOn': creds[2]['expiresOn'], 'subscription': subscription, 'tenant': tenant, 'resource': resource }
def login(username=None, password=None, service_principal=None, tenant=None): '''Log in to access Azure subscriptions''' interactive = False if username: if not password: import getpass password = getpass.getpass('Password: '******'az login' to authenticate through browser" if ('ID3242:' in msg) or ('Server returned an unknown AccountType' in msg): raise CLIError("The user name might be invalid. " + suggestion) if 'Server returned error in RSTR - ErrorCode' in msg: raise CLIError("Logging in through command line is not supported. " + suggestion) raise CLIError(err) except requests.exceptions.ConnectionError as err: raise CLIError('Please ensure you have network connection. Error detail: ' + str(err)) all_subscriptions = list(subscriptions) for sub in all_subscriptions: sub['cloudName'] = sub.pop('environmentName', None) return all_subscriptions
def _arm_get_resource_by_name(cli_ctx, resource_name, resource_type): """Returns the ARM resource in the current subscription with resource_name. :param str resource_name: The name of resource :param str resource_type: The type of resource """ result = get_resources_in_subscription(cli_ctx, resource_type) elements = [item for item in result if item.name.lower() == resource_name.lower()] if not elements: from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) message = "The resource with name '{}' and type '{}' could not be found".format( resource_name, resource_type) try: subscription = profile.get_subscription() raise CLIError("{} in subscription '{} ({})'.".format(message, subscription['name'], subscription['id'])) except (KeyError, TypeError): raise CLIError("{} in the current subscription.".format(message)) elif len(elements) == 1: return elements[0] else: raise CLIError( "More than one resources with type '{}' are found with name '{}'.".format( resource_type, resource_name))
def _graph_client_factory(**_): from azure.cli.core._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 _mock_get_mgmt_service_client(client_type, subscription_bound=True, subscription_id=None, api_version=None, base_url_bound=None, resource=CLOUD.endpoints.active_directory_resource_id, **kwargs): # version of _get_mgmt_service_client to use when recording or playing tests profile = Profile() cred, subscription_id, _ = profile.get_login_credentials(subscription_id=subscription_id, resource=resource) client_kwargs = {} if base_url_bound: client_kwargs = {'base_url': CLOUD.endpoints.resource_manager} if api_version: client_kwargs['api_version'] = api_version if kwargs: client_kwargs.update(kwargs) if subscription_bound: client = client_type(cred, subscription_id, **client_kwargs) else: client = client_type(cred, **client_kwargs) client = _debug.change_ssl_cert_verification(client) client.config.add_user_agent("AZURECLI/TEST/{}".format(core_version)) return (client, subscription_id)
def create_bot_json(cmd, client, resource_group_name, resource_name, app_password=None, raw_bot_properties=None): if not raw_bot_properties: raw_bot_properties = client.bots.get( resource_group_name=resource_group_name, resource_name=resource_name ) if not app_password: site_name = get_bot_site_name(raw_bot_properties.properties.endpoint) app_settings = get_app_settings( cmd=cmd, resource_group_name=resource_group_name, name=site_name ) app_password = [item['value'] for item in app_settings if item['name'] == 'MicrosoftAppPassword'][0] profile = Profile(cli_ctx=cmd.cli_ctx) return { 'type': 'abs', 'id': raw_bot_properties.name, 'name': raw_bot_properties.properties.display_name, 'appId': raw_bot_properties.properties.msa_app_id, 'appPassword': app_password, 'endpoint': raw_bot_properties.properties.endpoint, 'resourceGroup': str(resource_group_name), 'tenantId': profile.get_subscription(subscription=client.config.subscription_id)['tenantId'], 'subscriptionId': client.config.subscription_id }
def validate_lab_vm_list(namespace): """ Validates parameters for lab vm list and updates namespace. """ collection = [namespace.filters, namespace.all, namespace.claimable] if _any(collection) and not _single(collection): raise CLIError("usage error: [--filters FILTER | --all | --claimable]") # Retrieve all the vms of the lab if namespace.all: namespace.filters = None # Retrieve all the vms claimable by user elif namespace.claimable: namespace.filters = 'properties/allowClaim' # Default to retrieving users vms only else: # Find out owner object id if not namespace.object_id: from azure.cli.core._profile import Profile, CLOUD from azure.graphrbac.models import GraphErrorException profile = Profile() cred, _, tenant_id = profile.get_login_credentials( resource=CLOUD.endpoints.active_directory_graph_resource_id) graph_client = GraphRbacManagementClient(cred, tenant_id, base_url=CLOUD.endpoints.active_directory_graph_resource_id) subscription = profile.get_subscription() try: object_id = _get_current_user_object_id(graph_client) except GraphErrorException: object_id = _get_object_id(graph_client, subscription=subscription) namespace.filters = "Properties/ownerObjectId eq '{}'".format(object_id)
def loganalytics_data_plane_client(cli_ctx, _): """Initialize Log Analytics data client for use with CLI.""" from .vendored_sdks.loganalytics import LogAnalyticsDataClient from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) cred, _, _ = profile.get_login_credentials( resource="https://api.loganalytics.io") return LogAnalyticsDataClient(cred)
def show_subscription(subscription=None, expanded_view=None): profile = Profile() if not expanded_view: return profile.get_subscription(subscription) logger.warning("'--expanded-view' is deprecating and will be removed in a future release. You can get the same " "information using 'az cloud show'") return profile.get_expanded_subscription_info(subscription)
def _get_subscription_id_from_subscription(cli_ctx, subscription): # pylint: disable=inconsistent-return-statements profile = Profile(cli_ctx=cli_ctx) subscriptions_list = profile.load_cached_subscriptions() for sub in subscriptions_list: if sub['id'] == subscription or sub['name'] == subscription: return sub['id'] from azure.cli.core.util import CLIError raise CLIError("Subscription not found in the current context.")
def show_subscription(subscription=None, show_auth_for_sdk=None): import json profile = Profile() if not show_auth_for_sdk: return profile.get_subscription(subscription) # sdk-auth file should be in json format all the time, hence the print print(json.dumps(profile.get_sp_auth_info(subscription), indent=2))
def logout(username=None): """Log out to remove access to Azure subscriptions""" if _in_cloud_console(): raise CLIError(_CLOUD_CONSOLE_ERR_TEMPLATE.format('logout')) profile = Profile() if not username: username = profile.get_current_account_user() profile.logout(username)
def logout(cmd, username=None): """Log out to remove access to Azure subscriptions""" if in_cloud_console(): logger.warning(_CLOUD_CONSOLE_LOGOUT_WARNING) profile = Profile(cli_ctx=cmd.cli_ctx) if not username: username = profile.get_current_account_user() profile.logout(username)
def login(cmd, username=None, password=None, service_principal=None, tenant=None, allow_no_subscriptions=False, identity=False, use_device_code=False): """Log in to access Azure subscriptions""" from adal.adal_error import AdalError import requests # quick argument usage check if any([password, service_principal, tenant, allow_no_subscriptions]) and identity: raise CLIError("usage error: '--identity' is not applicable with other arguments") if any([password, service_principal, username, identity]) and use_device_code: raise CLIError("usage error: '--use-device-code' is not applicable with other arguments") interactive = False profile = Profile(cli_ctx=cmd.cli_ctx, async_persist=False) if identity: if in_cloud_console(): return profile.find_subscriptions_in_cloud_console() return profile.find_subscriptions_in_vm_with_msi(username) elif in_cloud_console(): # tell users they might not need login logger.warning(_CLOUD_CONSOLE_LOGIN_WARNING) if username: if not password: try: password = prompt_pass('Password: '******'Please specify both username and password in non-interactive mode.') else: interactive = True try: subscriptions = profile.find_subscriptions_on_login( interactive, username, password, service_principal, tenant, use_device_code=use_device_code, allow_no_subscriptions=allow_no_subscriptions) except AdalError as err: # try polish unfriendly server errors if username: msg = str(err) suggestion = "For cross-check, try 'az login' to authenticate through browser." if ('ID3242:' in msg) or ('Server returned an unknown AccountType' in msg): raise CLIError("The user name might be invalid. " + suggestion) if 'Server returned error in RSTR - ErrorCode' in msg: raise CLIError("Logging in through command line is not supported. " + suggestion) raise CLIError(err) except requests.exceptions.ConnectionError as err: raise CLIError('Please ensure you have network connection. Error detail: ' + str(err)) all_subscriptions = list(subscriptions) for sub in all_subscriptions: sub['cloudName'] = sub.pop('environmentName', None) return all_subscriptions
def create_keyvault(client, resource_group_name, vault_name, location=None, #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=None, tags=None): from azure.mgmt.keyvault.models import VaultCreateOrUpdateParameters from azure.cli.core._profile import Profile, CLOUD from azure.graphrbac.models import GraphErrorException profile = Profile() cred, _, tenant_id = profile.get_login_credentials( resource=CLOUD.endpoints.active_directory_graph_resource_id) graph_client = GraphRbacManagementClient(cred, tenant_id, base_url=CLOUD.endpoints.active_directory_graph_resource_id) # pylint: disable=line-too-long subscription = profile.get_subscription() if no_self_perms: access_policies = [] else: permissions = Permissions(keys=[KeyPermissions.get, KeyPermissions.create, KeyPermissions.delete, KeyPermissions.list, KeyPermissions.update, KeyPermissions.import_enum, KeyPermissions.backup, KeyPermissions.restore], secrets=[SecretPermissions.all], certificates=[CertificatePermissions.all]) try: object_id = _get_current_user_object_id(graph_client) except GraphErrorException: 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), 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 logout(username=None): """Log out to remove access to Azure subscriptions""" if in_cloud_console(): logger.warning(_CLOUD_CONSOLE_WARNING_TEMPLATE, 'logout') return profile = Profile() if not username: username = profile.get_current_account_user() profile.logout(username)
def applicationinsights_data_plane_client(cli_ctx, _, subscription=None): """Initialize Log Analytics data client for use with CLI.""" from .vendored_sdks.applicationinsights import ApplicationInsightsDataClient from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) cred, _, _ = profile.get_login_credentials( resource="https://api.applicationinsights.io", subscription_id=subscription ) return ApplicationInsightsDataClient(cred)
def cf_dls_filesystem(account_name): from azure.datalake.store import core profile = Profile() subscription_id = None cred, subscription_id, _ = profile.get_login_credentials( subscription_id=subscription_id, resource=CLOUD.endpoints.active_directory_data_lake_resource_id) return core.AzureDLFileSystem( token=cred, store_name=account_name, url_suffix=CLOUD.suffixes.azure_datalake_store_file_system_endpoint)
def _graph_client_factory(cli_ctx, **_): from azure.cli.core._profile import Profile from azure.cli.core.commands.client_factory import configure_common_settings from azure.graphrbac import GraphRbacManagementClient profile = Profile(cli_ctx=cli_ctx) cred, _, tenant_id = profile.get_login_credentials( resource=cli_ctx.cloud.endpoints.active_directory_graph_resource_id) client = GraphRbacManagementClient(cred, tenant_id, base_url=cli_ctx.cloud.endpoints.active_directory_graph_resource_id) configure_common_settings(cli_ctx, client) return client
def _get_subscription_id(): _, sub_id, _ = Profile().get_login_credentials(subscription_id=None) return sub_id
def get_token(server, resource, scope): # pylint: disable=unused-argument return Profile(cli_ctx=cli_ctx).get_login_credentials(resource)[0]._token_retriever() # pylint: disable=protected-access
def test_create_token_cache(self, mock_read_file): mock_read_file.return_value = [] profile = Profile(use_global_creds_cache=False) cache = profile._creds_cache.adal_token_cache self.assertFalse(cache.read_items()) self.assertTrue(mock_read_file.called)
def _get_profile(): from azure.cli.core._profile import Profile return Profile()
def _initialize_session(self): """ Creates a session using available authentication type. Auth priority: 1. Token Auth 2. Tenant Auth 3. Azure CLI Auth """ # Only run once if self.credentials is not None: return tenant_auth_variables = [ constants.ENV_TENANT_ID, constants.ENV_SUB_ID, constants.ENV_CLIENT_ID, constants.ENV_CLIENT_SECRET ] token_auth_variables = [ constants.ENV_ACCESS_TOKEN, constants.ENV_SUB_ID ] msi_auth_variables = [ constants.ENV_USE_MSI, constants.ENV_SUB_ID ] if self.authorization_file: self.credentials, self.subscription_id = self.load_auth_file(self.authorization_file) self.log.info("Creating session with authorization file") elif all(k in os.environ for k in token_auth_variables): # Token authentication self.credentials = BasicTokenAuthentication( token={ 'access_token': os.environ[constants.ENV_ACCESS_TOKEN] }) self.subscription_id = os.environ[constants.ENV_SUB_ID] self.log.info("Creating session with Token Authentication") self._is_token_auth = True elif all(k in os.environ for k in tenant_auth_variables): # Tenant (service principal) authentication self.credentials = ServicePrincipalCredentials( client_id=os.environ[constants.ENV_CLIENT_ID], secret=os.environ[constants.ENV_CLIENT_SECRET], tenant=os.environ[constants.ENV_TENANT_ID], resource=self.resource_namespace) self.subscription_id = os.environ[constants.ENV_SUB_ID] self.tenant_id = os.environ[constants.ENV_TENANT_ID] self.log.info("Creating session with Service Principal Authentication") elif all(k in os.environ for k in msi_auth_variables): # MSI authentication if constants.ENV_CLIENT_ID in os.environ: self.credentials = MSIAuthentication( client_id=os.environ[constants.ENV_CLIENT_ID], resource=self.resource_namespace) else: self.credentials = MSIAuthentication( resource=self.resource_namespace) self.subscription_id = os.environ[constants.ENV_SUB_ID] self.log.info("Creating session with MSI Authentication") else: # Azure CLI authentication self._is_cli_auth = True (self.credentials, self.subscription_id, self.tenant_id) = Profile().get_login_credentials( resource=self.resource_namespace) self.log.info("Creating session with Azure CLI Authentication") # Let provided id parameter override everything else if self.subscription_id_override is not None: self.subscription_id = self.subscription_id_override self.log.info("Session using Subscription ID: %s" % self.subscription_id) if self.credentials is None: self.log.error('Unable to locate credentials for Azure session.')
def create_keyvault( client, resource_group_name, vault_name, location=None, #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=None, tags=None): from azure.mgmt.keyvault.models import VaultCreateOrUpdateParameters from azure.cli.core._profile import Profile, CLOUD from azure.graphrbac.models import GraphErrorException profile = Profile() cred, _, tenant_id = profile.get_login_credentials( resource=CLOUD.endpoints.active_directory_graph_resource_id) graph_client = GraphRbacManagementClient(cred, tenant_id, base_url=CLOUD.endpoints.active_directory_graph_resource_id) # pylint: disable=line-too-long subscription = profile.get_subscription() if no_self_perms: access_policies = [] else: permissions = Permissions(keys=[ KeyPermissions.get, KeyPermissions.create, KeyPermissions.delete, KeyPermissions.list, KeyPermissions.update, KeyPermissions.import_enum, KeyPermissions.backup, KeyPermissions.restore ], secrets=[SecretPermissions.all], certificates=[CertificatePermissions.all]) try: object_id = _get_current_user_object_id(graph_client) except GraphErrorException: 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), 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 account_clear(): """Clear all stored subscriptions. To clear individual, use 'logout'""" profile = Profile() profile.logout_all()
def _get_aad_token_after_challenge(cli_ctx, token_params, login_server, only_refresh_token, repository, artifact_repository, permission, is_diagnostics_context): authurl = urlparse(token_params['realm']) authhost = urlunparse( (authurl[0], authurl[1], '/oauth2/exchange', '', '', '')) from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) # this might be a cross tenant scenario, so pass subscription to get_raw_token subscription = get_subscription_id(cli_ctx) creds, _, tenant = profile.get_raw_token(subscription=subscription) headers = {'Content-Type': 'application/x-www-form-urlencoded'} content = { 'grant_type': 'access_token', 'service': token_params['service'], 'tenant': tenant, 'access_token': creds[1] } response = requests.post(authhost, urlencode(content), headers=headers, verify=(not should_disable_connection_verify())) if response.status_code not in [200]: from ._errors import CONNECTIVITY_REFRESH_TOKEN_ERROR if is_diagnostics_context: return CONNECTIVITY_REFRESH_TOKEN_ERROR.format_error_message( login_server, response.status_code) raise CLIError( CONNECTIVITY_REFRESH_TOKEN_ERROR.format_error_message( login_server, response.status_code).get_error_message()) refresh_token = loads(response.content.decode("utf-8"))["refresh_token"] if only_refresh_token: return refresh_token authhost = urlunparse( (authurl[0], authurl[1], '/oauth2/token', '', '', '')) if repository: scope = 'repository:{}:{}'.format(repository, permission) elif artifact_repository: scope = 'artifact-repository:{}:{}'.format(artifact_repository, permission) else: # catalog only has * as permission, even for a read operation scope = 'registry:catalog:*' content = { 'grant_type': 'refresh_token', 'service': login_server, 'scope': scope, 'refresh_token': refresh_token } response = requests.post(authhost, urlencode(content), headers=headers, verify=(not should_disable_connection_verify())) if response.status_code not in [200]: from ._errors import CONNECTIVITY_ACCESS_TOKEN_ERROR if is_diagnostics_context: return CONNECTIVITY_ACCESS_TOKEN_ERROR.format_error_message( login_server, response.status_code) raise CLIError( CONNECTIVITY_ACCESS_TOKEN_ERROR.format_error_message( login_server, response.status_code).get_error_message()) return loads(response.content.decode("utf-8"))["access_token"]
def send_raw_request( cli_ctx, method, url, headers=None, uri_parameters=None, # pylint: disable=too-many-locals,too-many-branches,too-many-statements body=None, skip_authorization_header=False, resource=None, output_file=None, generated_client_request_id_name='x-ms-client-request-id'): import uuid from requests import Session, Request from requests.structures import CaseInsensitiveDict result = CaseInsensitiveDict() for s in headers or []: try: temp = shell_safe_json_parse(s) result.update(temp) except CLIError: key, value = s.split('=', 1) result[key] = value headers = result # If Authorization header is already provided, don't bother with the token if 'Authorization' in headers: skip_authorization_header = True # Handle User-Agent agents = [get_az_user_agent()] # Borrow AZURE_HTTP_USER_AGENT from msrest # https://github.com/Azure/msrest-for-python/blob/4cc8bc84e96036f03b34716466230fb257e27b36/msrest/pipeline/universal.py#L70 _ENV_ADDITIONAL_USER_AGENT = 'AZURE_HTTP_USER_AGENT' import os if _ENV_ADDITIONAL_USER_AGENT in os.environ: agents.append(os.environ[_ENV_ADDITIONAL_USER_AGENT]) # Custom User-Agent provided as command argument if 'User-Agent' in headers: agents.append(headers['User-Agent']) headers['User-Agent'] = ' '.join(agents) if generated_client_request_id_name: headers[generated_client_request_id_name] = str(uuid.uuid4()) # try to figure out the correct content type if body: try: _ = shell_safe_json_parse(body) if 'Content-Type' not in headers: headers['Content-Type'] = 'application/json' except Exception: # pylint: disable=broad-except pass # add telemetry headers['CommandName'] = cli_ctx.data['command'] if cli_ctx.data.get('safe_params'): headers['ParameterSetName'] = ' '.join(cli_ctx.data['safe_params']) result = {} for s in uri_parameters or []: try: temp = shell_safe_json_parse(s) result.update(temp) except CLIError: key, value = s.split('=', 1) result[key] = value uri_parameters = result or None endpoints = cli_ctx.cloud.endpoints # If url is an ARM resource ID, like /subscriptions/xxx/resourcegroups/xxx?api-version=2019-07-01, # default to Azure Resource Manager. # https://management.azure.com + /subscriptions/xxx/resourcegroups/xxx?api-version=2019-07-01 if '://' not in url: url = endpoints.resource_manager.rstrip('/') + url # Replace common tokens with real values. It is for smooth experience if users copy and paste the url from # Azure Rest API doc from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) if '{subscriptionId}' in url: url = url.replace( '{subscriptionId}', cli_ctx.data['subscription_id'] or profile.get_subscription_id()) # Prepare the Bearer token for `Authorization` header if not skip_authorization_header and url.lower().startswith('https://'): # Prepare `resource` for `get_raw_token` if not resource: # If url starts with ARM endpoint, like `https://management.azure.com/`, # use `active_directory_resource_id` for resource, like `https://management.core.windows.net/`. # This follows the same behavior as `azure.cli.core.commands.client_factory._get_mgmt_service_client` if url.lower().startswith(endpoints.resource_manager.rstrip('/')): resource = endpoints.active_directory_resource_id else: from azure.cli.core.cloud import CloudEndpointNotSetException for p in [x for x in dir(endpoints) if not x.startswith('_')]: try: value = getattr(endpoints, p) except CloudEndpointNotSetException: continue if isinstance(value, six.string_types) and url.lower().startswith( value.lower()): resource = value break if resource: # Prepare `subscription` for `get_raw_token` # If this is an ARM request, try to extract subscription ID from the URL. # But there are APIs which don't require subscription ID, like /subscriptions, /tenants # TODO: In the future when multi-tenant subscription is supported, we won't be able to uniquely identify # the token from subscription anymore. token_subscription = None if url.lower().startswith(endpoints.resource_manager.rstrip('/')): token_subscription = _extract_subscription_id(url) if token_subscription: logger.debug( 'Retrieving token for resource %s, subscription %s', resource, token_subscription) token_info, _, _ = profile.get_raw_token( resource, subscription=token_subscription) else: logger.debug('Retrieving token for resource %s', resource) token_info, _, _ = profile.get_raw_token(resource) token_type, token, _ = token_info headers = headers or {} headers['Authorization'] = '{} {}'.format(token_type, token) else: logger.warning( "Can't derive appropriate Azure AD resource from --url to acquire an access token. " "If access token is required, use --resource to specify the resource" ) # https://requests.readthedocs.io/en/latest/user/advanced/#prepared-requests s = Session() req = Request(method=method, url=url, headers=headers, params=uri_parameters, data=body) prepped = s.prepare_request(req) # Merge environment settings into session settings = s.merge_environment_settings( prepped.url, {}, None, not should_disable_connection_verify(), None) _log_request(prepped) r = s.send(prepped, **settings) _log_response(r) if not r.ok: reason = r.reason if r.text: reason += '({})'.format(r.text) raise CLIError(reason) if output_file: with open(output_file, 'wb') as fd: for chunk in r.iter_content(chunk_size=128): fd.write(chunk) return r
def get_token(server, resource, scope): # pylint: disable=unused-argument return Profile(cli_ctx=cli_ctx).get_raw_token(resource)[0]
class MediaV2Client(): """ Media V2 Client """ def __init__(self, cli_ctx, resource_group_name, account_name): from azure.cli.core._profile import Profile self.profile = Profile(cli_ctx=cli_ctx) self._old_rp_api_version = '2015-10-01' self.v2_media_api_resource = cli_ctx.cloud.endpoints.media_resource_id self.api_endpoint = self._get_v2_api_endpoint(cli_ctx, resource_group_name, account_name) self.access_token = self._get_v2_access_token() def _get_v2_api_endpoint(self, cli_ctx, resource_group_name, account_name): from msrestazure.tools import resource_id from azure.cli.command_modules.ams._sdk_utils import ( get_media_namespace, get_media_type) access_token = self.profile.get_raw_token()[0][2].get('accessToken') media_old_rp_url = resource_id( subscription=get_subscription_id(cli_ctx), resource_group=resource_group_name, namespace=get_media_namespace(), type=get_media_type(), name=account_name) + '?api-version={}'.format( self._old_rp_api_version) media_service_res = requests.get( cli_ctx.cloud.endpoints.resource_manager.rstrip('/') + media_old_rp_url, headers={'Authorization': 'Bearer {}'.format(access_token)}) if not media_service_res.ok: err_info = 'Request to 2015-10-01 Media API failed.' res_text = json.loads(media_service_res.text) if res_text is not None and res_text.get('error') is not None: err_info = res_text.get('error').get('message') raise CLIError(err_info) media_service = media_service_res.json() api_endpoints = media_service.get('properties').get('apiEndpoints') api_endpoint = next( (x for x in api_endpoints if x.get('majorVersion') == '2'), api_endpoints[0]) if not api_endpoint: raise CLIError('v2 Media API endpoint was not found.') return api_endpoint def _get_v2_access_token(self): # pylint: disable=protected-access access_token = self.profile.get_raw_token( resource=self.v2_media_api_resource)[0][2].get('accessToken') return access_token def set_mru(self, account_id, count, type): headers = {} headers['Authorization'] = 'Bearer {}'.format(self.access_token) headers['Content-Type'] = 'application/json;odata=verbose' headers['Accept'] = 'application/json;odata=verbose' url_request_template = "{}EncodingReservedUnitTypes(guid'{}')?api-version=2.19" response = requests.put( url_request_template.format(self.api_endpoint.get('endpoint'), account_id), headers=headers, data='{{"ReservedUnitType":{}, "CurrentReservedUnits":{}}}'.format( type, count)) if not response.ok: err_info = 'No error information available' if json.loads(response.text) is not None and json.loads( response.text).get('error') is not None: err_info = json.loads( response.text).get('error').get('message').get('value') raise CLIError( 'Request to EncodingReservedUnitTypes v2 API endpoint failed. ' + err_info) def get_mru(self): headers = {} headers['Authorization'] = 'Bearer {}'.format(self.access_token) headers['Content-Type'] = 'application/json;odata=minimalmetadata' headers['Accept'] = 'application/json;odata=minimalmetadata' headers['Accept-Charset'] = 'UTF-8' url_request_template = '{}EncodingReservedUnitTypes?api-version=2.19' response = requests.get(url_request_template.format( self.api_endpoint.get('endpoint')), headers=headers) if not response.ok: raise CLIError( 'Request to EncodingReservedUnitTypes v2 API endpoint failed.') return response.json().get('value')[0]
def set_active_subscription(subscription): """Set the current subscription""" if not id: raise CLIError('Please provide subscription id or unique name.') profile = Profile() profile.set_active_subscription(subscription)
def acs_create(resource_group_name, deployment_name, name, ssh_key_value, dns_name_prefix=None, content_version=None, admin_username="******", agent_count="3", agent_vm_size="Standard_D2_v2", location=None, master_count="3", orchestrator_type="dcos", service_principal=None, client_secret=None, tags=None, custom_headers=None, raw=False, **operation_config): #pylint: disable=too-many-locals """Create a new Acs. :param resource_group_name: The name of the resource group. The name is case insensitive. :type resource_group_name: str :param deployment_name: The name of the deployment. :type deployment_name: str :param dns_name_prefix: Sets the Domain name prefix for the cluster. The concatenation of the domain name and the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. :type dns_name_prefix: str :param name: Resource name for the container service. :type name: str :param ssh_key_value: Configure all linux machines with the SSH RSA public key string. Your key should include three parts, for example 'ssh-rsa AAAAB...snip...UcyupgH azureuser@linuxvm :type ssh_key_value: str :param content_version: If included it must match the ContentVersion in the template. :type content_version: str :param admin_username: User name for the Linux Virtual Machines. :type admin_username: str :param agent_count: The number of agents for the cluster. Note, for DC/OS clusters you will also get 1 or 2 public agents in addition to these seleted masters. :type agent_count: str :param agent_vm_size: The size of the Virtual Machine. :type agent_vm_size: str :param location: Location for VM resources. :type location: str :param master_count: The number of DC/OS masters for the cluster. :type master_count: str :param orchestrator_type: The type of orchestrator used to manage the applications on the cluster. Possible values include: 'dcos', 'swarm' :type orchestrator_type: str or :class:`orchestratorType <Default.models.orchestratorType>` :param service_principal: The service principal used for cluster authentication to Azure APIs. If not specified, it is created for you and stored in the ${HOME}/.azure directory. :type service_principal: str :param client_secret: The secret associated with the service principal. If --service-principal is specified, then secret should also be specified. If --service-principal is not specified, the secret is auto-generated for you and stored in ${HOME}/.azure/ directory. :param tags: Tags object. :type tags: object :param dict custom_headers: headers that will be added to the request :param bool raw: returns the direct response alongside the deserialized response :rtype: :class:`AzureOperationPoller<msrestazure.azure_operation.AzureOperationPoller>` instance that returns :class:`DeploymentExtended <Default.models.DeploymentExtended>` :rtype: :class:`ClientRawResponse<msrest.pipeline.ClientRawResponse>` if raw=true :raises: :class:`CloudError<msrestazure.azure_exceptions.CloudError>` """ if not dns_name_prefix: # Use subscription id to provide uniqueness and prevent DNS name clashes _, subscription_id, _ = Profile().get_login_credentials( subscription_id=None) dns_name_prefix = '{}-{}-{}'.format(name, resource_group_name, subscription_id[0:6]) register_providers() groups = _resource_client_factory().resource_groups # Just do the get, we don't need the result, it will error out if the group doesn't exist. groups.get(resource_group_name) if orchestrator_type == 'Kubernetes' or orchestrator_type == 'kubernetes': from azure.cli.command_modules.role.custom import _graph_client_factory # TODO: This really needs to be broken out and unit tested. client = _graph_client_factory() if not service_principal: # --service-principal not specified, try to load it from local disk principalObj = load_acs_service_principal() if principalObj: service_principal = principalObj.get('service_principal') client_secret = principalObj.get('client_secret') _validate_service_principal(client, service_principal) else: # Nothing to load, make one. if not client_secret: client_secret = binascii.b2a_hex( os.urandom(10)).decode('utf-8') salt = binascii.b2a_hex(os.urandom(3)).decode('utf-8') url = 'http://{}.{}.{}.cloudapp.azure.com'.format( salt, dns_name_prefix, location) service_principal = _build_service_principal( client, name, url, client_secret) logger.info('Created a service principal: %s', service_principal) store_acs_service_principal(client_secret, service_principal) # Either way, update the role assignment, this fixes things if we fail part-way through _add_role_assignment('Owner', service_principal) else: # --service-principal specfied, validate --client-secret was too if not client_secret: raise CLIError( '--client-secret is required if --service-principal is specified' ) _validate_service_principal(client, service_principal) return _create_kubernetes(resource_group_name, deployment_name, dns_name_prefix, name, ssh_key_value, admin_username=admin_username, agent_count=agent_count, agent_vm_size=agent_vm_size, location=location, service_principal=service_principal, client_secret=client_secret) ops = get_mgmt_service_client(ACSClient).acs return ops.create_or_update(resource_group_name, deployment_name, dns_name_prefix, name, ssh_key_value, content_version=content_version, admin_username=admin_username, agent_count=agent_count, agent_vm_size=agent_vm_size, location=location, master_count=master_count, orchestrator_type=orchestrator_type, tags=tags, custom_headers=custom_headers, raw=raw, operation_config=operation_config)
def load_subscriptions(all_clouds=False, refresh=False): profile = Profile() if refresh: subscriptions = profile.refresh_accounts() subscriptions = profile.load_cached_subscriptions(all_clouds) return subscriptions
def _get_data_credentials(cli_ctx, subscription_id=None): from azure.cli.core._profile import Profile profile = Profile(cli_ctx=cli_ctx) creds, _, _ = profile.get_login_credentials(subscription_id=subscription_id, resource="https://quantum.microsoft.com") return creds
def get_subscription_id(cli_ctx): from azure.cli.core._profile import Profile if not cli_ctx.data.get('subscription_id'): cli_ctx.data['subscription_id'] = Profile( cli_ctx=cli_ctx).get_subscription_id() return cli_ctx.data['subscription_id']
def _authenticate(self): try: keyvault_client_id = self._auth_params.get('keyvault_client_id') keyvault_secret_id = self._auth_params.get('keyvault_secret_id') # If user provided KeyVault secret, we will pull auth params information from it if keyvault_secret_id: self._auth_params.update( json.loads( get_keyvault_secret(keyvault_client_id, keyvault_secret_id))) client_id = self._auth_params.get('client_id') client_secret = self._auth_params.get('client_secret') access_token = self._auth_params.get('access_token') tenant_id = self._auth_params.get('tenant_id') use_msi = self._auth_params.get('use_msi') subscription_id = self._auth_params.get('subscription_id') if access_token and subscription_id: log.info("Creating session with Token Authentication") self.subscription_id = subscription_id self.credentials = BasicTokenAuthentication( token={'access_token': access_token}) self._is_token_auth = True elif client_id and client_secret and tenant_id and subscription_id: log.info( "Creating session with Service Principal Authentication") self.subscription_id = subscription_id self.credentials = ServicePrincipalCredentials( client_id=client_id, secret=client_secret, tenant=tenant_id, resource=self.resource_namespace) self.tenant_id = tenant_id elif use_msi and subscription_id: log.info("Creating session with MSI Authentication") self.subscription_id = subscription_id if client_id: self.credentials = MSIAuthentication( client_id=client_id, resource=self.resource_namespace) else: self.credentials = MSIAuthentication( resource=self.resource_namespace) elif self._auth_params.get('enable_cli_auth'): log.info("Creating session with Azure CLI Authentication") self._is_cli_auth = True (self.credentials, self.subscription_id, self.tenant_id) = Profile().get_login_credentials( resource=self.resource_namespace) log.info("Session using Subscription ID: %s" % self.subscription_id) except AuthenticationError as e: log.error('Azure Authentication Failure\n' 'Error: {0}'.format( json.dumps(e.inner_exception.error_response, indent=2))) sys.exit(1) except HTTPError as e: if keyvault_client_id and keyvault_secret_id: log.error( 'Azure Authentication Failure\n' 'Error: Cannot retrieve SP credentials from the Key Vault ' '(KV uses MSI to access) with client id: {0}'.format( keyvault_client_id)) elif use_msi: log.error( 'Azure Authentication Failure\n' 'Error: Could not authenticate using managed service identity {0}' .format(client_id if client_id else '(system identity)')) else: log.error('Azure Authentication Failure: %s' % e.response) sys.exit(1) except CLIError as e: log.error( 'Azure Authentication Failure\n' 'Error: Could not authenticate with Azure CLI credentials: {0}' .format(e)) sys.exit(1) except Exception as e: log.error('Azure Authentication Failure\n' 'Error: {0}'.format(e)) sys.exit(1)
def fzf_customer(cmd, fzf_filter=None, no_default=False): """ Use fzf to quickly filter and select your current customer. """ from azure.cli.core._profile import Profile from azure.cli.core.api import load_subscriptions subscriptions = load_subscriptions(cmd.cli_ctx, all_clouds=False, refresh=False) if "AZ_FZF_CUSTOMER_SUBSCRIPTIONS" not in os.environ: raise CLIError('Specify the path to subscriptions.yml in ' 'AZ_FZF_CUSTOMER_SUBSCRIPTIONS environment variable') subscriptions_yml_path = os.environ['AZ_FZF_CUSTOMER_SUBSCRIPTIONS'] if not os.path.isfile(subscriptions_yml_path): raise CLIError('"%s" is not a file' % subscriptions_yml_path) customer_subscriptions = {} try: with open(subscriptions_yml_path) as subscriptions_yml: customer_subscriptions = yaml.safe_load(subscriptions_yml) except yaml.YAMLError as exc: error_msg = "" if hasattr(exc, 'problem_mark'): if exc.context != None: error_msg = (' parser says\n' + str(exc.problem_mark) + '\n ' + str(exc.problem) + ' ' + str(exc.context) + '\nPlease correct data and retry.') else: error_msg = (' parser says\n' + str(exc.problem_mark) + '\n ' + str(exc.problem) + '\nPlease correct data and retry.') else: error_msg = ("Something went wrong while parsing yaml file") raise CLIError('Error parsing %s\n%s' % (subscriptions_yml_path, error_msg)) except OSError as exc: print() raise CLIError('Something went wrong while opening "%s": %s' % (subscriptions_yml_path, exc)) if not customer_subscriptions: raise CLIError('No subscriptions found in subscriptions.yml') headers = ["Customer", "Name", "ID"] subs_sorted = sorted(customer_subscriptions, key=lambda i: i["customer"]) subs_list = [[sub["customer"], sub["name"], sub["id"]] for sub in subs_sorted] result = _fzf(_fzf_table(subs_list, headers), header_lines=2, fzf_filter=fzf_filter) if result: subscription = result.split('|')[-2].strip() if not no_default: LOGGER.info('setting default customer') Profile(cli_ctx=cmd.cli_ctx).set_active_subscription(subscription) return next((s for s in subscriptions if s["id"] == subscription)) return None
def create_service_principal_for_rbac(name=None, password=None, years=1, #pylint:disable=too-many-arguments,too-many-statements,too-many-locals scopes=None, role='Contributor', expanded_view=None, skip_assignment=False): '''create a service principal and configure its access to Azure resources :param str name: a display name or an app id uri. Command will generate one if missing. :param str password: the password used to login. If missing, command will generate one. :param str years: Years the password will be valid. :param str scopes: space separated scopes the service principal's role assignment applies to. Defaults to the root of the current subscription. :param str role: role the service principal has on the resources. ''' import time graph_client = _graph_client_factory() role_client = _auth_client_factory().role_assignments scopes = scopes or ['/subscriptions/' + role_client.config.subscription_id] sp_oid = None sp_created = False _RETRY_TIMES = 24 app_display_name = None if name and not '://' in name: app_display_name = name name = "http://" + name #normalize be a valid graph service principal name if name: query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name) aad_sps = list(graph_client.service_principals.list(filter=query_exp)) if aad_sps: sp_oid = aad_sps[0].object_id app_id = aad_sps[0].app_id #pylint: disable=protected-access if not sp_oid: start_date = datetime.datetime.utcnow() app_display_name = app_display_name or ('azure-cli-' + start_date.strftime('%Y-%m-%d-%H-%M-%S')) if name is None: name = 'http://' + app_display_name # just a valid uri, no need to exist end_date = start_date + relativedelta(years=years) password = password or str(uuid.uuid4()) aad_application = create_application(graph_client.applications, display_name=app_display_name, #pylint: disable=too-many-function-args homepage='http://'+app_display_name, identifier_uris=[name], available_to_other_tenants=False, password=password, start_date=start_date, end_date=end_date) #pylint: disable=no-member app_id = aad_application.app_id #retry till server replication is done for l in range(0, _RETRY_TIMES): try: aad_sp = _create_service_principal(app_id, resolve_app=False) break except Exception as ex: #pylint: disable=broad-except #pylint: disable=line-too-long if l < _RETRY_TIMES and 'The appId of the service principal does not reference a valid application object' in str(ex): time.sleep(5) logger.warning('Retrying service principal creation: %s/%s', l+1, _RETRY_TIMES) else: logger.warning("Creating service principal failed for appid '%s'. Trace followed:\n%s", name, ex.response.headers) #pylint: disable=no-member raise sp_oid = aad_sp.object_id sp_created = True #retry while server replication is done if not skip_assignment: # pylint: disable=line-too-long for scope in scopes: for l in range(0, _RETRY_TIMES): try: _create_role_assignment(role, sp_oid, None, scope, resolve_assignee=False) break except Exception as ex: if l < _RETRY_TIMES and ' does not exist in the directory ' in str(ex): time.sleep(5) logger.warning('Retrying role assignment creation: %s/%s', l+1, _RETRY_TIMES) continue elif sp_created: #dump out history for diagnoses logger.warning('Role assignment creation failed. Traces followed:\n') logger.warning('Service principal response: %s\n', aad_sp.response.headers) if getattr(ex, 'response', None) is not None: logger.warning('role assignment response: %s\n', ex.response.headers) #pylint: disable=no-member raise if expanded_view: from azure.cli.core._profile import Profile profile = Profile() result = profile.get_expanded_subscription_info(scopes[0].split('/')[2] if scopes else None, app_id, password) else: result = { 'appId': app_id, 'password': password, 'name': name, 'displayName': app_display_name, 'tenant': graph_client.config.tenant_id } return result
def test_endpoint_none(self): with self.assertRaises(CloudEndpointNotSetException): profile = Profile() profile.get_login_credentials()