diff --git a/src/azure-cli/azure/cli/command_modules/acr/_help.py b/src/azure-cli/azure/cli/command_modules/acr/_help.py index dad7cefb4f3..7ea6a5c9f61 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_help.py @@ -342,7 +342,7 @@ helps['acr login'] = """ type: command short-summary: Log in to an Azure Container Registry through the Docker CLI. -long-summary: Docker must be installed on your machine. Once done, use `docker logout ` to log out. (If you only need an access token and do not want to install Docker, specify '--expose-token') +long-summary: Docker must be installed on your machine. Once done, use `docker logout ` to log out. (If you only need a refresh token and do not want to install Docker, specify '--expose-token') examples: - name: Log in to an Azure Container Registry text: > diff --git a/src/azure-cli/azure/cli/command_modules/acr/_params.py b/src/azure-cli/azure/cli/command_modules/acr/_params.py index c52aaaef53c..1977b6f1294 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acr/_params.py @@ -168,7 +168,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements c.argument('days', type=int, help='The number of days to retain a soft-deleted manifest or tag after which it gets purged (Range: 1 to 90). Default is 7.') with self.argument_context('acr login') as c: - c.argument('expose_token', options_list=['--expose-token', '-t'], help='Expose access token instead of automatically logging in through Docker CLI', action='store_true') + c.argument('expose_token', options_list=['--expose-token', '-t'], help='Expose refresh token instead of automatically logging in through Docker CLI', action='store_true') with self.argument_context('acr repository') as c: c.argument('resource_group_name', deprecate_info=c.deprecate(hide=True)) diff --git a/src/azure-cli/azure/cli/command_modules/acr/custom.py b/src/azure-cli/azure/cli/command_modules/acr/custom.py index 24aad21f4e8..f9826cb474a 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acr/custom.py @@ -299,17 +299,25 @@ def acr_login(cmd, password=password, resource_group_name=resource_group_name) - logger.warning("You can perform manual login using the provided access token below, " - "for example: 'docker login loginServer -u %s -p accessToken'", EMPTY_GUID) + logger.warning("Note: The token in both the accessToken and refreshToken fields is " + "an ACR Refresh Token, not an ACR Access Token. This ACR Refresh Token cannot be used " + "directly to authenticate with registry APIs such as pushing/pulling images and listing " + "repositories/tags. This ACR Refresh Token must be subsequently exchanged for an ACR Access." + "Please see https://aka.ms/acr/auth/oauth") + + logger.warning("You can perform manual login using the provided refresh token below, " + "for example: 'docker login loginServer -u %s -p refreshToken'", EMPTY_GUID) token_info = { "loginServer": login_server, - "accessToken": password + "username": EMPTY_GUID, + "accessToken": password, + "refreshToken": password } return token_info - tips = "You may want to use 'az acr login -n {} --expose-token' to get an access token, " \ + tips = "You may want to use 'az acr login -n {} --expose-token' to get a refresh token, " \ "which does not require Docker to be installed.".format(registry_name) from azure.cli.core.util import in_cloud_console diff --git a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_commands.py b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_commands.py index f5b4d78e146..1a5366c3b2d 100644 --- a/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_commands.py @@ -5,7 +5,7 @@ from azure.cli.testsdk.scenario_tests import AllowLargeResponse from azure.cli.testsdk import ScenarioTest, ResourceGroupPreparer, KeyVaultPreparer, record_only, live_only -from azure.cli.command_modules.acr.custom import DEF_DIAG_SETTINGS_NAME_TEMPLATE +from azure.cli.command_modules.acr.custom import DEF_DIAG_SETTINGS_NAME_TEMPLATE, EMPTY_GUID from azure.cli.core.commands.client_factory import get_subscription_id import time @@ -94,7 +94,30 @@ def test_check_name_availability_dnl_scope(self): self.check('nameAvailable', True), self.check_pattern('availableLoginServerName',r'{name}-[a-zA-Z0-9]+\.*') ]) + + @live_only() + @ResourceGroupPreparer() + def test_acr_login_expose_token(self, resource_group): + registry_name = self.create_random_name('clireg', 20) + + self.kwargs.update({ + 'registry_name': registry_name, + 'rg': resource_group, + 'sku': 'Premium' + }) + + self.cmd('acr create -n {registry_name} -g {rg} --sku {sku}', + checks=[self.check('name', '{registry_name}'), + self.check('provisioningState', 'Succeeded')]) + + tokens = self.cmd('acr login -n {} --expose-token'.format(registry_name), checks=[ + self.exists('accessToken'), + self.exists('refreshToken'), + self.exists('loginServer'), + self.check('username', EMPTY_GUID)]).get_output_in_json() + self.assertEqual(tokens['accessToken'], tokens['refreshToken']) + @ResourceGroupPreparer() @live_only() def test_acr_create_with_managed_registry(self, resource_group, resource_group_location):