Posts in this Series
In the last post, we took a look at the Connect-AzAccount
command, stored its output in a variable using the Outvariable parameter and explored it. I think we ought to go through a few of the other commands in the Az.Accounts module and see why we didn’t need to dig in such as we did. As I said previously, it was a good exercise, but it’s almost like the cmdlet developers wanted to provide us with an easier way to gather Azure account-related information. We’ll know more soon enough. First things first, let’s pull back only the Get
commands from the Az.Accounts PowerShell module. Again, we’re going to use some formatting commands, but because we only want to view our results on the screen.
Get-Command -Module Az.Accounts -Verb Get | Format-Table -AutoSize
CommandType Name Version Source
----------- ---- ------- ------
Alias Get-AzDomain 2.8.0 Az.Accounts
Cmdlet Get-AzAccessToken 2.8.0 Az.Accounts
Cmdlet Get-AzConfig 2.8.0 Az.Accounts
Cmdlet Get-AzContext 2.8.0 Az.Accounts
Cmdlet Get-AzContextAutosaveSetting 2.8.0 Az.Accounts
Cmdlet Get-AzDefault 2.8.0 Az.Accounts
Cmdlet Get-AzEnvironment 2.8.0 Az.Accounts
Cmdlet Get-AzSubscription 2.8.0 Az.Accounts
Cmdlet Get-AzTenant 2.8.0 Az.Accounts
If you read the last post, then commands such as Get-AzEnvironment
and Get-AzContext
might seem to make sense here. The nouns in those commands were the two, base properties in our $AzOutput
variable. Let’s see what they return and compare it to what we saw in the output variable in the Accounts – Azure with PowerShell II post.
Get-Environment
Name Resource Manager Url ActiveDirectory Authority Type
---- -------------------- ------------------------- ----
AzureGermanCloud https://management.microsoftazure.de/ https://login.microsoftonline.de/ Built-in
AzureCloud https://management.azure.com/ https://login.microsoftonline.com/ Built-in
AzureUSGovernment https://management.usgovcloudapi.net/ https://login.microsoftonline.us/ Built-in
AzureChinaCloud https://management.chinacloudapi.cn/ https://login.chinacloudapi.cn/ Built-in
versus
$AzOutput.Environments
Key Value
--- -----
AzureGermanCloud AzureGermanCloud
AzureCloud AzureCloud
AzureUSGovernment AzureUSGovernment
AzureChinaCloud AzureChinaCloud
It’s clear, that by default the Get-Environment
cmdlet returns the information we saw previously. Still, by default, it includes some additional information. While I didn’t show the output in the previous post, I did include $AzOutput.Environments.Values
. This will give the same results as above, but let’s use what they’ve provided us. The same goes for using Get-AzContext
even though it produces the same exact information as $AzOutput.Context
. Whoa, whoa. It doesn’t, we lost the Name property using our output variable. The cmdlets, that we should use, create complete objects; again, let’s stick with these.
Get-AzContext | Format-List
Name : Free Trial (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) - xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tommymaynard@xxxxxx
Account : tommymaynard@xx.xxx
Environment : AzureCloud
Subscription : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Tenant : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
TokenCache :
VersionProfile :
ExtendedProperties : {}
$AzOutput.Context | Format-List
Name :
Account : tommymaynardxxxxxx
Environment : AzureCloud
Subscription : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Tenant : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
TokenCache :
VersionProfile :
ExtendedProperties : {}
There was more to the Get started with Azure PowerShell document that I overlooked. Let’s head back there. If you’re new to PowerShell then it’s a must that you learn how to find commands using Get-Command
and even Get-Module
. Also, use Get-Help
to explore information about a specific command. These are some of the early-on basics to learn when you’re new to PowerShell. No one knows what every command does; they just know how to find out. A portion of this page covered this topic, too.
One final thing I found on the sign into Azure section of the page, was the UseDeviceAuthentication
parameter. Using this, we don’t have to supply a username and corresponding password, but instead, using this parameter generated a device code in PowerShell to use at a specific URL, which is all included in the image below.
Reading that, lead me to the Sign in with Azure PowerShell page. I should’ve known, there are plenty of other ways to authenticate to Azure, besides using the two interactive methods we’ve discussed so far. One is signing in with a service principal using password-based authentication and the other is certificate-based authentication. There’s also signing in using a managed identity. The rest you can explore at your leisure, but we should work through using a service principal using password-based authentication—why not!?
In the password-based authentication link above, the first thing to notice is the need to invoke the New-AzADServicePrincipal
command. Before we invoke a command that will most likely make changes, such as a New-
command likely would, we want, no we need, to learn more. First, in what module is the command included?
Get-Command -Name New-AzADServicePrincipal | Format-Table -AutoSize
CommandType Name Version Source
----------- ---- ------- ------
Function New-AzADServicePrincipal 6.0.0 Az.Resources
What’s the purpose of the Azure PowerShell Az.Resources module?
Get-Module -Name Az.Resources | Select-Object -Property Name,Description | Format-List
Name : Az.Resources
Description : Microsoft Azure PowerShell - Azure Resource Manager and Active Directory cmdlets in Windows PowerShell and PowerShell Core. Manages subscriptions, tenants, resource groups, deployment templates, providers, and resource permissions in Azure Resource
Manager. Provides cmdlets for managing resources generically across resource providers.
For more information on Resource Manager, please visit the following: https://docs.microsoft.com/azure/azure-resource-manager/
For more information on Active Directory, please visit the following: https://docs.microsoft.com/azure/active-directory/fundamentals/active-directory-whatis
What does the New-AzADServicePrincipal
command do?
Get-Help -Name New-AzADServicePrincipal | Select-Object -Property Name,Synopsis
Name Synopsis
---- --------
New-AzADServicePrincipal Adds new entity to servicePrincipals
Is there a Get-
Version of the command (Get-AzADServicePrincipal
)?
Get-Command -Name Get-AzADServicePrincipal | Format-Table -AutoSize
CommandType Name Version Source
----------- ---- ------- ------
Function Get-AzADServicePrincipal 6.0.0 Az.Resources
And if so, what output does it produce?
Get-AzADServicePrincipal | Select-Object -Property AppDisplayName
AppDisplayName
--------------
Office 365 Configure
Azure SQL Managed Instance to Microsoft.Network
Microsoft Graph
Microsoft Modern Contact Master
Azure Resource Graph
Billing RP
Jarvis Transaction Service
AIGraphClient
Microsoft_Azure_Support
Windows Azure Security Resource Provider
Azure SQL Database Backup To Azure Backup Vault
Azure Data Warehouse Polybase
Microsoft.Azure.ActiveDirectoryIUX
Microsoft Azure App Service
Policy Administration Service
Azure Portal
Azure SQL Virtual Network to Network Resource Provider
Azure Classic Portal
Azure Monitor System
Microsoft.SupportTicketSubmission
Azure ESTS Service
Windows Azure Active Directory
Azure Traffic Manager and DNS
Microsoft.Azure.GraphExplorer
Microsoft App Access Panel
Microsoft Azure Signup Portal
Signup
Microsoft.SMIT
Windows Azure Service Management API
Okay, we should feel as though we know a little bit more about our next move. First, however, check out the Azure Portal view of this output. The instructions can be found in the View the service principal subtopic. Sure enough, it looks almost exactly like the above output when we don’t use | Select-Object -Property AppDisplayName
, and display the GUIDs.
First, we need to obtain and store our Tenant ID.
$TenantId = (Get-AzContext).Tenant.Id
$TenantId
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Then we’ll use the New-AzADServicePrincipal
command, among a few other commands to create a new Service Principal and get connected to Azure using it.
$ServicePrincipal = New-AzADServicePrincipal -DisplayName SPName
$ServicePrincipal
DisplayName Id AppId
----------- -- -----
SPName xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
After this step, we can go back into the Azure Portal and find a new entry. The command worked!
The $ServicePrincipal
variable includes more information than its output displays by default. We should be getting used to that by now. It includes a PasswordCredentials property that includes several other nested properties.
$ServicePrincipal.PasswordCredentials
CustomKeyIdentifier DisplayName EndDateTime Hint KeyId SecretText StartDateTime
------------------- ----------- ----------- ---- ----- ---------- -------------
5/30/2023 1:08:45 AM Qcw xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Qcw8Q......oRLla5 5/30/2022 1:08:45 AM
One of those nested properties is SecretText. That is our password and we’re going to use it to create a credential object—the combination of a user and its password.
$ServicePrincipal.PasswordCredentials.SecretText
Qcw8Q......oRLla5
As we’ll see, the username is the AppId’s GUID. When we supply both it and the password, as is done in the below PowerShell, we’ll have our complete PSCredential object.
$PSCredential = Get-Credential -UserName $ServicePrincipal.AppId
PowerShell credential request
Enter your credentials.
Password for user xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx: ****************************************
Using the PSCredential object, we can 100% authenticate to Azure using PowerShell in another manner. We haven’t researched it or discussed it yet—although we should have—but the purpose for why we’d use a service principal should be included. The first paragraph on the Create an Azure service principal with Azure PowerShell page explains it well. Read that. Back with more Azure PowerShell in time!
Connect-AzAccount -ServicePrincipal -Credential $PSCredential -Tenant $TenantId
WARNING: The provided service principal secret will be included in the 'AzureRmContext.json' file found in the user profile ( C:\Users\tommymaynard\.Azure ). Please ensure that this directory has appropriate protections.
Account SubscriptionName TenantId Environment
------- ---------------- -------- -----------
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx AzureCloud