Using Azure CLI Authentication within Local Containers
If you do Azure development and use containers, then you may rue the day that v2.33 of the Azure CLI was released!
When testing your work in a local container you'll often need to authenticate with Azure resources, a Key Vault or Storage Account for example.
Using Azure CLI Credentials in Docker
Previously, you could take advantage of how the Azure CLI stored your access token in a JSON file within your user profile area (i.e. c:/users/<your-username>/.azure
). You could login to the Azure CLI as normal and then run your container with a host volume mount (aka bind mount) - whereby you mount your .azure
folder inside the container so that it appears in the equivalent location for the user running the containerised process (e.g. /root/.azure
).
But why do we even care about the Azure CLI, I thought we were talking about testing our own code in a container?
Some brief context: The Azure SDK includes the DefaultAzureCredential
class which provides a mechanism for our code to transparently attempt a series of authentication methods, from using credentials stored in environment variables through to using a managed identity (if available). One such method is to use Azure CLI credentials, when available.
The volume mount mentioned above makes the Azure CLI credentials on your local machine available to your app running inside the container. The result of which is that the app can seamlessly authenticate to Azure without having to handle explicit credentials inside the container. This gives us a low-friction dev inner loop that is a real boon for developer productivity. (NOTE: This does require your app's container image to include the Azure CLI.)
Azure CLI Creds broken in Docker on Windows
You knew it was coming, things can never remain this easy! Since v2.33 of the Azure CLI, on Windows, the JSON file that stores your access token has been replaced with an encrypted file. The rub here is that the Mac and Linux versions of the Azure CLI still use the old file.
https://github.com/Azure/azure-sdk-for-net/issues/19167#issuecomment-1034029384
This means when you use the volume mount 'trick', your app running in a Linux container can no longer read your access token, so any Azure authentication the app requires fails - and with it our low friction dev inner loop!
There has been a lot discussion about this issue and how it is a retrograde step in terms of developer productivity. The counter argument is that the change has improved the security of how the time-limited access token is stored. However, in practice, all this really has done is to drive developers to use a service principal inside their container. The credentials for which can be passed-in via environment variables, from (yes you guessed it!) a clear-text script sat on the hard-drive that we endeavour not to accidentally commit to source control.
How to fix Azure CLI Credentials in Docker
A few workarounds have been suggested elsewhere, but I've not seen this method mentioned so thought it would be worth sharing.
There are 2 options for setting-up this workaround:
- Using WSL, if you have it installed
- Using Docker, if you don't
Setting Azure CLI Credentials using WSL
It's debatable whether this option is easier than the next one, but it does give me the opportunity to show a less well-known feature of the Azure CLI.
We've already discussed how Azure CLI uses the .azure
folder to store its access token (amongst other things). What if we could make it use a different folder?
As it happens you can! By setting the AZURE_CONFIG_DIR
environment variable you can override the default path.
Using this to our advantage, we can create alternative .azure
folder that has the Linux-friendly JSON file needed by the containerised app (you need to have previously installed the Azure CLI inside WSL):
Open a WSL console:
cd /mnt/c/users/<your-username>
mkdir .azure-for-docker
AZURE_CONFIG_DIR=./.azure-for-docker az login
This should open the normal browser-based login experience. Once logged-in you should see the usual set of files & folders in the directory you created.
You can jump to the using it section now.
Setting Azure CLI Credentials using Docker
If you don't have WSL available, then you can do this using any container image that has the Azure CLI available - in the steps below I use the official Azure CLI image.
Open a PowerShell console:
cd $HOME
md .azure-for-docker
cd .azure-for-docker
docker pull mcr.microsoft.com/azure-cli
docker run -it —rm -v "$($PWD):/root/.azure" mcr.microsoft.com/azure-cli az login
You won't get the seamless browser login like the WSL option, instead you'll need use the device code login flow, but if successful you should see the usual set of files & folders in the directory you created.
Using Azure CLI Creds with Docker on Windows
If all has gone well the new folder created during the setup now contains valid Azure CLI credentials that are usable from within a Linux container.
Let's test it!
Open a PowerShell console:
docker run -it —-rm -v "$($HOME)/.azure-for-docker:/root/.azure" mcr.microsoft.com/azure-cli
az group list
Hopefully you saw a list of all the resource groups in your default subscription?
Now you can return to those halcyon days of a super smooth dev inner loop without the burden of knowing you have a permanent credential lying around on your hard drive.
Just remember when the access token in your .azure-for-docker
folder expires you'll need to repeat one of the above login steps. If you can live with the device flow login experience, then adding the following to your PowerShell profile will give you a handy alias to quickly login:
function azlogin-docker { docker run --rm -it -v "$($HOME)/.azure-for-docker:/root/.azure" mcr.microsoft.com/azure-cli az login }
Using the above, refreshing your Azure CLI token is now as easy as typing azlogin-docker
, complete the browser login process and then you are good to go.