Tag Archives: Azure

A Return to PowerShell

After 20+ years, and 5+ positions in education (K-12 and higher ed), I’ve taken a new position. It’s still Information Technology at the end of the day, but now I’ll be working in the healthcare industry. There’s plenty of reasons to be excited. One is that I’ll be better positioned to use my PowerShell and automation skills again. Two, I’m moving from an employer that’s AWS-focused to one that’s Azure focused. What an amazing opportunity! I ventured into Security Engineering, but now it’s back to Systems Engineering for me. It was a great experience and opportunity, but like any new position—well, usually anyway—I’m excited about what’s next.

I was in my interview and the time came when I could ask questions. I asked, in relation to work, “If you had an unlimited budget and cost was of no concern, what would you do?” My new lead said he’d take everything to Azure. Okay, sign me up! It was in later 2020 when I picked up Azure and Microsoft 365 certificates; hopefully, they may be put to use soon.

I’m hopeful that this position provides me the opportunity to create new content and to share new things I learn about Azure PowerShell and just PowerShell, as well. I miss writing, but with more day-to-day opportunities to work with PowerShell, I know what will happen. I’ve done this PowerShell writing thing for greater than eight year. So with that, hopefully, I’ll be back with something new soon.

I wrote the above portion of this post weeks ago, and now I’ve completed two full weeks at the new job, and guess what I did yesterday afternoon? I wrote a PowerShell script for a colleague. I took a starter script and fixed it so it could be run from anywhere and access a flat file in the same directory—thanks $PSScriptRoot. I also added a bunch of features to it, which while they may not be necessary, was exciting for me. I worked with so much I missed. I wrote more PowerShell yesterday than I did in the last year and a half in my security position. My thought is this: In security, you have to buy tools; you have to have a reputable company behind what you use. In systems, that isn’t required; you can automate without the same concerns. It’s good to be back.

Accounts Continued – Azure with PowerShell III

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

Modifying the New-Guid Cmdlet

I’m deep in the weeds right now writing new content about my experience with Azure and Azure PowerShell. So, what a better time to have an idea, write a quick function, and then create its own post and publish it. Or, maybe not. It’s quick and easy and I think there are people for which this might be good. You can create a function that will run in place of a PowerShell cmdlet, in order to add additional features, take them away, or whatever other reason, or reasons, one might have. That said, and you may notice this momentarily, just because my function of the same name runs instead of the cmdlet, doesn’t mean there isn’t a way to run the original cmdlet.

As one might expect, GUIDs are used all over Azure for identification purposes. I’m running into them everywhere. I don’t want to publish the GUIDs associated with my Tenant, Subscription, etc., so I’ve been replacing mine with this: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Well, since I use PowerShell to shave off all the seconds I can, I now have a function that will give me an X GUID–we’ll call it–if that’s what I want. We’ll start with an example of it being used, which will then be followed by the code to make that happen. If you’re curious why my New-Guid function runs in place of the cmdlet with the same name from the Microsoft.PowerShell.Utility PowerShell module, then read up on the PowerShell command precedence rules. This is what to remember about the order, however:

  1. Alias
  2. Function
  3. Cmdlet
  4. External executable files (programs and non-PowerShell scripts)
New-Guid

Guid
----
d6dde62e-46fc-4f37-b75a-c116f003a270
New-Guid -x

Guid
----
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

And, here’s the function that makes the above invocations a possibility. I’ll drop it in my profile script and then it’ll be available in my PowerShell session right when I need it, just like New-Guid already was.

function New-Guid {
    [CmdletBinding()]
    Param (
        [Parameter()]
        [switch]$x
    )

    if ($x)
    {
        [PSCustomObject]@{'Guid' = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'}
    }
    else
    {
        Microsoft.PowerShell.Utility\New-Guid
    }
}

If you’re like me, perhaps you just had an idea. Allow it to accept any single character and create the GUID with the character. Okay, back to what I should be doing with this time.

It Begins – Azure with PowerShell I

Posts in this Series

I had a conversation with someone recently, which reminded me of an event in my life. I was sitting in the yard, maybe up to 15 years ago, pulling weeds. In southern Arizona, getting rid of the weeds is what you do, one way or another. Either you do it, or you pay someone else to do it. While I’ve yet to pay for such a service, I remember thinking, why am I doing this? Why am I sitting in the yard during the weekend when I could be sitting in the house and learning more about this IT career of mine? My competition is in there … figuratively. They’re learning more than me now, sitting here, learning nothing, except which weeds are going to leave a sticky residue on my fingertips, or poke me, or never come out of the earth with the roots intact, ever. Every minute I’m not learning more about what I do, someone else is gaining an advantage over me. More dollars, more vacations, more iRobot vacuums, which I hear are great–that’s what this person was telling me–but how would I know?

Don’t get me wrong, everyone has to have non-work-related hobbies and things to do, but pulling weeds probably isn’t it.

So, I am beginning my journey into Azure, alongside PowerShell. Or just maybe, I have that backward: My journey into PowerShell, alongside Azure. No. I have over 10 years’ worth of PowerShell experience and we’ll say a couple of years of Azure? I did receive an Azure (and M365) Fundamentals certificate, so maybe I know something. It’s been a while though, as I work closely with AWS five days a week. Regardless of how I think about this though, I’m going to learn one with the help of the other. I’ve done this before; I started with the cmdlets first: “I’m just starting to get my hands wet with Microsoft Lync. As I often do, I use the Windows PowerShell cmdlets to help learn more about a product; I did this same thing with Hyper-V.” Then, once I’m comfortable with those, maybe I head into the UI and see if I can duplicate what the commands do.

I recommend you do as I did, and begin with the two, below posts to get started with Azure PowerShell. These are quick, easy reads, one of which will assist with ensuring you have the Azure PowerShell module installed.

While I’ve been writing about PowerShell for a while, I think with this series, I’m going to approach things as though my visitors aren’t as experienced with PowerShell as my normal audience. So, if you’re my normal audience, some of the PowerShell concepts I mention may seem a touch basic, but with good reason. Knowing PowerShell and learning how to make things happen, is much different than knowing a product or service, and then learning PowerShell.

And bonus, the 8.0.0 version of the Az PowerShell module was released, today. That’s right, Tuesday, May 24, 2022–the first day of this series. The below, Find-Modulecommand, searches the PowerShell Gallery for the module and populates the $AzModuleInfo variable full of information–not just the Name, Version, and PublishedDate, although Select-Object does filter the output after the variable collects it all. Be sure to inspect the variable closely to view all the things that it contains. While Find-Module won’t install the module, Install-Module will. Before you run away with that command, though, read the two above links. More soon!

Find-Module -Name Az -OutVariable AzModuleInfo | Select-Object -Property Name,Version,PublishedDate

Name Version PublishedDate
---- ------- -------------
Az   8.0.0   5/24/2022 1:05:02 AM
$AzModuleInfo | Select-Object -Property *
Name                       : Az
Version                    : 8.0.0
Type                       : Module
Description                : Microsoft Azure PowerShell - Cmdlets to manage resources in Azure. This module is compatible with PowerShell and Windows PowerShell.
                             For more information about the Az module, please visit the following: https://docs.microsoft.com/powershell/azure/
Author                     : Microsoft Corporation
CompanyName                : azure-sdk...