Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{Core} az login: support --scope #17778

Merged
merged 4 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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