Skip to content

Commit

Permalink
{Core} az login: support --scope (#17778)
Browse files Browse the repository at this point in the history
* add scope for az login

* Fix linter

* Fix linter

* Update src/azure-cli/azure/cli/command_modules/profile/__init__.py
  • Loading branch information
yonzhan authored Apr 21, 2021
1 parent 84b1aef commit 0216604
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 9 deletions.
21 changes: 13 additions & 8 deletions src/azure-cli-core/azure/cli/core/_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from azure.cli.core._environment import get_config_dir
from azure.cli.core._session import ACCOUNT
from azure.cli.core.util import get_file_json, in_cloud_console, open_page_in_browser, can_launch_browser,\
is_windows, is_wsl
is_windows, is_wsl, scopes_to_resource
from azure.cli.core.cloud import get_active_cloud, set_cloud_subscription

logger = get_logger(__name__)
Expand Down Expand Up @@ -172,6 +172,7 @@ def find_subscriptions_on_login(self,
password,
is_service_principal,
tenant,
scopes=None,
use_device_code=False,
allow_no_subscriptions=False,
subscription_finder=None,
Expand All @@ -180,6 +181,11 @@ def find_subscriptions_on_login(self,
allow_debug_adal_connection()
subscriptions = []

if scopes:
auth_resource = scopes_to_resource(scopes)
else:
auth_resource = self._ad_resource_uri

if not subscription_finder:
subscription_finder = SubscriptionFinder(self.cli_ctx,
self.auth_ctx_factory,
Expand All @@ -193,14 +199,14 @@ def find_subscriptions_on_login(self,
try:
authority_url, _ = _get_authority_url(self.cli_ctx, tenant)
subscriptions = subscription_finder.find_through_authorization_code_flow(
tenant, self._ad_resource_uri, authority_url)
tenant, self._ad_resource_uri, authority_url, auth_resource=auth_resource)
except RuntimeError:
use_device_code = True
logger.warning('Not able to launch a browser to log you in, falling back to device code...')

if use_device_code:
subscriptions = subscription_finder.find_through_interactive_flow(
tenant, self._ad_resource_uri)
tenant, self._ad_resource_uri, auth_resource=auth_resource)
else:
if is_service_principal:
if not tenant:
Expand Down Expand Up @@ -638,7 +644,6 @@ def get_msal_token(self, scopes, data):
if 'error' in result:
logger.warning(result['error_description'])

from azure.cli.core.util import scopes_to_resource
token_entry = self._login_with_authorization_code_flow(tenant, scopes_to_resource(scopes))
result = cred.acquire_token_by_refresh_token(token_entry['refreshToken'], scopes, data=data)

Expand Down Expand Up @@ -894,9 +899,9 @@ def find_from_user_account(self, username, password, tenant, resource):
result = self._find_using_specific_tenant(tenant, token_entry[_ACCESS_TOKEN])
return result

def find_through_authorization_code_flow(self, tenant, resource, authority_url):
def find_through_authorization_code_flow(self, tenant, resource, authority_url, auth_resource=None):
# launch browser and get the code
results = _get_authorization_code(resource, authority_url)
results = _get_authorization_code(auth_resource or resource, authority_url)

if not results.get('code'):
raise CLIError('Login failed') # error detail is already displayed through previous steps
Expand All @@ -913,9 +918,9 @@ def find_through_authorization_code_flow(self, tenant, resource, authority_url):
result = self._find_using_specific_tenant(tenant, token_entry[_ACCESS_TOKEN])
return result

def find_through_interactive_flow(self, tenant, resource):
def find_through_interactive_flow(self, tenant, resource, auth_resource=None):
context = self._create_auth_context(tenant)
code = context.acquire_user_code(resource, _CLIENT_ID)
code = context.acquire_user_code(auth_resource or resource, _CLIENT_ID)
logger.warning(code['message'])
token_entry = context.acquire_token_with_device_code(resource, code, _CLIENT_ID)
self.user_id = token_entry[_TOKEN_ENTRY_USER_ID]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def load_arguments(self, command):
c.argument('use_device_code', action='store_true',
help="Use CLI's old authentication flow based on device code. CLI will also use this if it can't launch a browser in your behalf, e.g. in remote SSH or Cloud Shell")
c.argument('use_cert_sn_issuer', action='store_true', help='used with a service principal configured with Subject Name and Issuer Authentication in order to support automatic certificate rolls')
c.argument('scopes', options_list=['--scope'], nargs='+', help='Used in the /authorize request. It can cover only one static resource.')

with self.argument_context('logout') as c:
c.argument('username', help='account user, if missing, logout the current active account')
Expand Down
3 changes: 2 additions & 1 deletion src/azure-cli/azure/cli/command_modules/profile/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def account_clear(cmd):

# pylint: disable=inconsistent-return-statements
def login(cmd, username=None, password=None, service_principal=None, tenant=None, allow_no_subscriptions=False,
identity=False, use_device_code=False, use_cert_sn_issuer=None):
identity=False, use_device_code=False, use_cert_sn_issuer=None, scopes=None):
"""Log in to access Azure subscriptions"""
from adal.adal_error import AdalError
import requests
Expand Down Expand Up @@ -155,6 +155,7 @@ def login(cmd, username=None, password=None, service_principal=None, tenant=None
password,
service_principal,
tenant,
scopes=scopes,
use_device_code=use_device_code,
allow_no_subscriptions=allow_no_subscriptions,
use_cert_sn_issuer=use_cert_sn_issuer)
Expand Down

0 comments on commit 0216604

Please sign in to comment.