Skip to content
2 changes: 1 addition & 1 deletion src/azure-cli/azure/cli/command_modules/acr/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <registry url>` 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 <registry url>` 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: >
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli/azure/cli/command_modules/acr/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
16 changes: 12 additions & 4 deletions src/azure-cli/azure/cli/command_modules/acr/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down