CLI ? or command line interface ? because the clickety click in the Azure portal gets real old real quick! The thing is, the Azure portal is great, but as soon as I'm done doing something, I want to document it. That means taking lots of screenshots, marking them nicely with annotations, and then saving those screenshots in a folder, referencing them in markdown, and, because I use a retina screen, those screenshots are never the right size! Ugh!

I could just write up Azure CLI commands instead. That way, I can automate stuff, it's documented, checked in, version controlled, repeatable, and frankly, it isn't much more effort than doing it in the portal. In fact, I'd argue that Azure CLI almost makes me never actually use the portal, except for trivial one-time use-and-toss things!

So what is the Azure CLI? It's the cross-platform command line experience that lets you manage Azure resources.

Fair Warning

All right, I'm going to get some flak for this, but this article is severely opinionated toward the *nix shell. I realize that Azure CLI runs fine on a DOS prompt. And I also realize that this is purely my opinion. But let's be honest, PowerShell works better on Windows. I realize there's a PowerShell for Mac as well, but it never seems to have the commands I need. All the modules I love to use don't work my Mac. Meanwhile, I love the *nix terminal; it's so much more powerful than the usual DOS prompt. When I think of Azure CLI, I just go with the assumption that it's running on some sort of environment that's *nix.

The good news is that even on Windows, you can easily get the *nix shell. It's really not a showstopper.

Use Azure CLI Without Installing It

The best part about Azure CLI is that you don't really need to install it to use it. Simply open your browser and visit https://shell.azure.com. Before you know it, you're using Azure CLI right within the browser. You can see it running in Figure 1.

Figure 1: Using Azure CLI in the browser
Figure 1: Using Azure CLI in the browser

You can access Azure CLI directly from your mobile phone as well. Just download the Azure app and look for the cloud shell icon on the bottom right. Tapping on it brings up Azure CLI right on your phone. This can be seen in Figure 2.

Figure 2: Azure CLI on my phone
Figure 2: Azure CLI on my phone

There's something really awesome about being able to automate the power of the cloud from your phone.

Install Azure CLI

Although accessing Azure CLI from the browser is convenient and accessing from the phone is cool, let's be honest. You'll frequently want to install Azure CLI. Why? Because installing it on your local computer allows greater control, better typing experience, an environment and shell you can customize to your liking, etc.

You can install Azure CLI on Mac, Windows, or Linux. Or, if you prefer, you can even run it as a Docker image. Here's how you can do any of the four.

To install Azure CLI on Windows, you can use this command.

Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi;
Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'

Running this command downloads the Azure CLI installer and installs it. If you have Azure CLI already installed, this command updates it.

To install Azure CLI on Mac OS, you can use homebrew. Once homebrew is installed, go ahead and run the command below:

brew update && brew install azure-cli

Similarly, if you wish to upgrade Azure CLI on a Mac, run this command:

brew upgrade azure-cli

On Linux, you can install Azure CLI using the below command:

curl -sL  https://aka.ms/InstallAzureCLIDeb | sudo bash

Let's say that you don't want to install WSL and you don't want to install Azure CLI. Just use Docker. Simply use the command below to install Azure CLI as a Docker image.

docker run -it mcr.microsoft.com/azure-cli

As you can see, this is one of the reasons that Azure CLI is so popular. It runs everywhere, it runs easily, and it's consistent across various operating systems.

Use Azure CLI

No matter how you installed Azure CLI and on what OS, the process of using it is consistent. This is a big deal because it bridges the differences among operating systems. Now you can check in your Azure CLI scripts and be assured that they'll work for your co-workers, no matter what OS they use.

This is why I prefer to do this on a *nix operating system. Invariably you'll see open source projects that write Azure CLI commands in shell scripts87 intertwined with *nix commands. Just make your life easier and install WSL on Windows.

To use Azure CLI, you type “az” on your terminal prompt. Writing this command throws a wall of ASCII at you. It shows all the commands you can use. Pick any of those commands. For instance, “vm” is a valid command that lets you manage Linux or Windows virtual machines. Run this command on terminal:

az vm

This should produce an output, as shown in Figure 3.

Figure 3: Output of az vm
Figure 3: Output of az vm

As you can see, this command shows you all the sub commands that “az vm” supports. For instance, “az vm create”. If you ever wish to find out how to use that command, you simply say “az vm create -h”, for help text. This writes out examples, documentation, and all that good stuff you need to get going with this command.

This is another thing I love about Azure CLI, it teaches itself to you.

Azure CLI Login

Azure CLI exposes a number of commands, but hardly any of them are usable unless you log in first. I think it's quite important to understand how the log in process works, not only as a user of Azure CLI but also behind the scenes, because more and more other CLIs, such as Terraform, are piggybacking on this mechanism.

To login using Azure CLI, you simply issue this command:

az login 

Running this command launches your operating system browser. At this point, you do your usual Azure AD login and go back to your terminal. All of the usual advantages of the Azure AD login apply here, such as security policies, threat detection, MFA, etc., to keep your Azure CLI login experience protected.

What really happened here? Azure CLI acts as a native client. The process of authentication was similar to that of any first-class identity citizen. At the end of authentication, it stores a refresh token and access token pair in ~/.azure/TokenCache.dat.

Now, any third-party CLI can piggyback on this authenticated session. This truly simplifies the job of other CLIs. There are a number of additional files in that same folder, so feel free to explore further.

As you can see, the browser pops open to authenticate you. But what if you don't have the flexibility of launching the browser? For instance, let's say that you run Azure CLI as a Docker container. Or perhaps you SSH into another computer and wish to launch Azure CLI from there? It's simple; you issue the command like this:

az login --use-device-code

Using this login mechanism, you're now using an alternate authentication mechanism called the device code flow. This mechanism gives you a code that you can type into a URL and perform authentication, so there's no dependence on the native browser. Once you're authenticated, you can party as usual.

You can also choose to log in as a service principal using the command:

az login --service-principal   -u <username> -p <password> -t <tenant>

You will find logging in as a service principal particularly useful when automating various processes, such as in Azure DevOps pipelines or unattended processes. Another particularly useful trick using service principals is when you wish to get access tokens for any random API that you wish to test. More on that later in this article.

Another really amazing feature of Azure is managed identity. Managed identity is an identity that you assign to an Azure resource so that resource can do things as that identity. This is a great feature because you have no password to manage; the identity is self-contained within Azure.

You could have a Docker container, or perhaps a virtual machine, or perhaps an app service, that's given an Azure identity. Wouldn't it be nice to use Azure CLI under the permissions of that managed identity from within that process? You can do so using this command:

az login --identity

You can use managed identities or service principals to perform automation scenarios. We all know that certain APIs are stubborn, albeit those are very few. Those APIs must require a user identity, or perhaps your boss dictates that you must use a user identity for some silly reason. Azure CLI can entirely skip the browser for authentication and allow you to specify credentials directly in the login command. You can do so using the command shown below.

az login -u <username> -p <password>

I must discourage you from using this approach as much as you can. Not only do you have the headache of managing that username and password, this approach won't work if you use things such as MFA. Behind the scenes, this mechanism uses something called the ROPC grant, which suffers from numerous issues. You can read more about it here https://winsmarts.com/ropc-prefer-strongly-to-use-8b99039573d8.

Finally, sometimes you may wish to use Azure CLI without an Azure subscription. For instance, you may want to manage an Azure AD that has no Azure subscriptions tied to it. You can do so using this command:

az login --allow-no-subscriptions

As you can see, there's almost no conceivable situation that they haven't thought of. This makes Azure CLI a very versatile tool.

So now you've logged in using Azure CLI, but what can you do with it?

Tenants and Subscriptions

An important concept to know is that Azure AD is tied to a tenant, i.e., one tenant on Azure AD. However, you may have multiple subscriptions attached to a tenant. Additionally, your login account, for example, sahilmalik@tenantxyz.onmicrosoft.com may have access to another subscription in a completely different tenant, such as tenantabc.onmicrosoft.com.

This is, in fact, a very common scenario, given that companies frequently hire third parties to manage certain functions in their Azure subscriptions. This is all tied down using Azure RBAC (role-based access control).

Why I bring this up now is because soon, as you login using Azure CLI, you'll have authenticated as a user, or service principal etc. But this identity can have access to numerous subscriptions in your tenant or other tenants.

You can easily see the subscriptions attached to your account using the command below.

az account list

Like any other Azure CLI command, if you wish to learn how to manage these accounts, you can issue the command below.

az account -h

As can you see, you can switch subscriptions using the set command or view the current subscription using the show command.

Azure CLI Interactive Mode

Perhaps the best part of using Azure CLI is that it teaches itself to you. You can write --help or shorthand -h in front of any command, and it writes out exactly what you can do.

But there is an even cooler way to learn: Azure CLI interactive mode. You can start this mode using this command:

az interactive ?update

Running this command turns your entire terminal into an interactive studio, as can be seen in Figure 4.

Figure 4: Azure CLI in interactive mode
Figure 4: Azure CLI in interactive mode

This is quite incredible, really. There's a lot of interesting detail in Figure 4. You can see basic help for the command and parameters you're using, and it'll even show you examples as you build your command by showing you IntelliSense. It's a great way to get started with Azure CLI.

This is where the fun ends. The first time I saw Azure CLI interactive, I was blown away. But as I got more proficient with Azure CLI, I felt that it slowed me down. It's a great way to get started with or familiarize yourself with a new command set, but once you get used to the underlying commands, you'll just type them yourself, zippity fast.

Once you get used to the underlying commands, you'll just type them yourself, zippity fast.

Azure CLI Auto Complete

Interactive mode may feel too heavy after a while. And constantly typing -h to understand what commands are available may feel annoying. There's a middle ground, and that's autocomplete.

Autocomplete simply means that you can type a command partially and then hit the Tab key and your shell will show you the various autocompletions available for the typed command.

To enable autocomplete, just issue this command at terminal:

autoload -U +X bashcompinit && bashcompinitsource /usr/local/etc/bash_completion.d/az

Now type in any partial Azure CLI command, hit Tab, and you'll be shown autocomplete choices, as can be seen in Figure 5.

Figure 5: Azure CLI autocomplete
Figure 5: Azure CLI autocomplete

You can hit Tab repeatedly to scroll through the various options, which even works on command parameters, as can be seen in Figure 6.

Figure 6: Azure CLI autocomplete on parameters
Figure 6: Azure CLI autocomplete on parameters

Azure CLI Query Results

Frequently, you'll run a command and it spews out a wall of JSON in your face. For instance, if you have many service principals in your subscription, you can run a command, such as the one in the next snippet, to list all the service principals in your tenant.

az ad sp list --all

The output will be a bit of a shock. It scrolls out reams of JSON super fast! What if all you wanted was to know the names of those service principals?

Every Azure CLI command supports a --query input flag. You can simply pass in a query parameter that lets you do basic things, such as perform some basic filtering, or extract and show some basic properties. This command is:

az ad sp list --query "[].appDisplayName"

Running this command writes out only the app display name property of all the apps in your subscription.

I don't know about you, but frequently, when I'm trying to figure out complex queries in a complex JSON document, I can't seem to come up with the JMES query in the first go. I wish there were an interactive way to play with the data and figure out the query I want. That's where jpterm/jmespath-terminal comes in. The jpterm/jmespath-terminal is a Python package that gives you an interactive UI to work with JMES queries. To use it, first go ahead and install it, like this:

pip install jmespath-terminal

Oh wait, what is “pip”? Well, it's a Python package installer. If you don't have it on your OS, run a Google/Bing search for it and install pip first. Once you have it installed, you can run this command:

az ad sp list | jpterm

Now you'll see a user interface like that shown in Figure 7.

Figure 7: JMES queries in an interactive mode

Now you can play around with the data to your heart's content and figure out exactly the JMES query you need. This really simplifies the task for building JMES queries.

Remember, you're on a Unix shell. So you don't have to rely on JMES as the only querying mechanism. For instance, I can simply request the results as a table, pick column #2 using awk, and get the results using a single command, like this:

az ad sp list --output table | awk '//{print $2}'

As you can imagine, as you get more proficient, you'll start interacting with the power of Azure at the speed of thought.

The Azure CLI Find Extension

This section was hard to name. It's not about “finding an extension,” it's about an extension called “find.”

Azure CLI is awesome but it isn't enough. For instance, you may want to extend it yourself, for your organization, and you'll want to author extensions to do so. Microsoft has authored a number of such extensions for various products also. You can find the various extensions that Microsoft offers at https://docs.microsoft.com/en-us/cli/azure/azure-cli-extensions-overview.

One of my favorite extensions is the find extension. The find extension talks to a Microsoft AI-powered API called Azure Aladdin, and helps you find commands. Let's take it for a spin.

The first step is to install the extension using the command below.

az extension add -n find

If you wish to use this extension, you type “az find” and, as usual, you can ask for help using az find -h.

Imagine that I wanted to do something but I don't quite remember what the exact command was. For instance, let's say that I want to create a virtual machine. I can simply issue a command like this:

az find "create vm"

The output of this command can be seen in Figure 8.

Figure 8: Output of the Find command
Figure 8: Output of the Find command

As you can see from Figure 8, the AI-based engine tried to interpret what I was trying to do and gave the exact command, and even command examples, on how to achieve that.

Azure CLI Debug Mode

Azure CLI can do some amazing things with so many valuable commands. I frequently find myself scratching my head, thinking, hmm?how did they do that? I mean, I'm sure some really smart folks have figured out some amazing code and REST API calls to get the information they need. And sometimes I want to have similar functionality in my applications.

For example, the command az group list lists all resource groups. And for some crazy reason, I wish to know what REST API I can call to get the same information in my applications.

Well, you simply issue the command:

az group list --debug --verbose

This command scrolls a lot of text, but inside that text, it clearly shows the REST URL that a request was made to. It shows the details of the request and the response received. Now all you have to do is copy-and-paste that URL into your app, make sure that it has a valid access token and the necessary permissions, and make the same REST call as Azure CLI showed you. Voila, you should have the same results!

Get the Access Token

I'll bet you've seen or heard of products like Microsoft Graph and that there's a lot of power behind Microsoft Graph. Really, Graph is just a bunch of well-documented REST APIs. Calling the REST API isn't hard and figuring out how to get an access token to call the API is the fun part.

Azure CLI can get you an access token. You might ask why you should use Azure CLI to get an access token. There are two situations. First, in your automation scripts, you might wish to do some automation that requires Microsoft Graph, or, for that matter, any Azure AD-protected API. Second, you've written an API, you wish to test it, and the onerous process of hand-performing auth code flow isn't the best thing to do on a lazy afternoon.

In either of those two cases, Azure CLI can help.

As long as you're logged into Azure CLI, you can request a token for Microsoft Graph using the following command:

az account get-access-token --resource https://<a href="http://graph.microsoft.com">graph.microsoft.com</a>

Really, that's how simple it is. No more opening a browser window, performing a sign in, catching a redirect, grabbing the auth code, and then replaying the auth code on a POST request to the authorization endpoint to get an access token. All of that can be simplified with just that one call.

I do have some bad news for you. This approach will only work for a small list of white-listed APIs that Azure CLI has access to. For a more generic mechanism that lets you get an access token for any API, use a service principal. Here's how.

Create an app:

az ad app create --display-name sampleApp --identifier-uris <identifier_uri>

Next, create a service principal.

az ad sp create-for-rbac --name dellaterserviceprincipal 

Once this service principal is created, carefully note down the created appid (username) and password.

Next, login using Azure CLI as this service principal.

az login --service-principal --username "appid" --password "pasword" --tenant "tenantid"

Now that you are logged in, request an access token.

az account get-access-token --resource <resource_uri>

This simple command will save you loads of headaches if you're authoring Azure AD protected APIs or simply testing other APIs.

Summary

I haven't even begun to touch the surface of the productivity superpowers that Azure CLI gives you. Once you start combining Azure CLI with the power of the Unix terminal, you can move at the speed of thought. Pair that with the power of Azure, and now you're seriously talking about the next level in productivity.

Just a few years ago, we were shipping servers, replacing hard disks, and plugging in network cables. Now, a few keystrokes on a keyboard, and you have a globally distributed datacenter ready to go.

I can't wait to see what we'll build in the next few years.

Until next time, be careful with those Azure credits.