Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from azure.cli.core.commands.parameters import get_enum_type

from azure.cli.command_modules.profile._format import transform_account_list
from ._validators import validate_tenant
import azure.cli.command_modules.profile._help # pylint: disable=unused-import

cloud_resource_types = ["oss-rdbms", "arm", "aad-graph", "ms-graph", "batch", "media", "data-lake"]
Expand Down Expand Up @@ -47,7 +48,7 @@ def load_arguments(self, command):
c.argument('password', options_list=['--password', '-p'], help="Credentials like user password, or for a service principal, provide client secret or a pem file with key and public certificate. Will prompt if not given.")
c.argument('service_principal', action='store_true', help='The credential representing a service principal.')
c.argument('username', options_list=['--username', '-u'], help='user name, service principal, or managed service identity ID')
c.argument('tenant', options_list=['--tenant', '-t'], help='The AAD tenant, must provide when using service principals.')
c.argument('tenant', options_list=['--tenant', '-t'], help='The AAD tenant, must provide when using service principals.', validator=validate_tenant)
c.argument('allow_no_subscriptions', action='store_true', help="Support access tenants without subscriptions. It's uncommon but useful to run tenant level commands, such as 'az ad'")
c.ignore('_subscription') # hide the global subscription parameter
c.argument('identity', options_list=('-i', '--identity'), action='store_true', help="Log in using the Virtual Machine's identity", arg_group='Managed Service Identity')
Expand Down
38 changes: 38 additions & 0 deletions src/azure-cli/azure/cli/command_modules/profile/_validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import uuid

from azure.cli.core.util import should_disable_connection_verify
from knack.log import get_logger

logger = get_logger(__name__)


def _is_guid(guid):
try:
uuid.UUID(guid)
return True
except ValueError:
pass
Copy link
Contributor

@yugangw-msft yugangw-msft Sep 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can return False here

Copy link
Member Author

@jiasli jiasli Sep 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! All _is_guids are fixed.

return False


def validate_tenant(cmd, namespace):
"""
Make sure tenant is a GUID. If domain name is provided, resolve to GUID.
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc#fetch-the-openid-connect-metadata-document
"""
if not _is_guid(namespace.tenant):
import requests
active_directory_endpoint = cmd.cli_ctx.cloud.endpoints.active_directory
url = '{}/{}/.well-known/openid-configuration'.format(active_directory_endpoint, namespace.tenant)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metadata = requests.get(url, verify=not should_disable_connection_verify()).json()

# Example issuer: https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/
tenant_id = metadata['issuer'].split("/")[3]

logger.warning('Resolve tenant domain name %s to GUID %s', namespace.tenant, tenant_id)
namespace.tenant = tenant_id