Simplifying Cloud Management with Azure Automation Accounts

Managing cloud resources can feel like juggling too many balls at once: updates, monitoring, compliance, and resource optimization. That’s where Azure Automation Accounts come in, a powerful tool that automates time-consuming and repetitive tasks so IT pros can focus on what truly matters.

In this post, we’ll break down what Azure Automation Accounts are, how they work, their key features, real-world use cases, and how you can get started quickly.

What is an Azure Automation Account?

An Azure Automation Account is a centralized hub in Microsoft Azure where you can manage automation resources. It acts as a container for all the components you need to automate cloud tasks, such as:

  • Runbooks (scripts for tasks)
  • Schedules (timing your scripts)
  • Modules (PowerShell or Python libraries)
  • Hybrid workers (agents that run automation tasks on-prem or in other clouds)

In short, it’s your automation command center.

Key Features

Here are some standout features that make Azure Automation Accounts a must-have:

Runbooks

These are scripts that perform tasks like restarting VMs, rotating keys, or cleaning up unused resources. You can write them in PowerShell, Python, or use the Graphical Runbook Designer for drag-and-drop simplicity.

Scheduling

Automate tasks to run on a set schedule, like checking VM health every morning or scaling services during off-peak hours.

Hybrid Runbook Workers

Need to automate tasks on your on-prem servers? Hybrid Runbook Workers extend your automation capabilities beyond Azure.

Update Management

Keep your Windows and Linux VMs compliant with automated patching and update assessments.

Credential and Certificate Management

Securely store credentials, certificates, and other secrets directly in the automation account, keeping sensitive info safe.

Benefits for IT Professionals

  • Reduce Manual Effort: Save time by automating routine tasks.
  • Improve Consistency: Eliminate human error with repeatable scripts.
  • Boost Efficiency: Focus on strategic projects instead of repetitive admin.
  • Hybrid Flexibility: Automate tasks across on-prem, multi-cloud, and Azure environments.

PowerShell Script to create Azure Automation Account

I put together this PowerShell script to create Azure automation account.

Login to Azure using Connect-AzAccount

This script will,

  • Check and validate the name entered
  • Query Azure to ensure the location value entered is valid
  • Query logged in Azure subscription to validate the resource group name entered
  • Asks for the plan – Basic or Free
  • Asks if you want to generate and assign a new System Identity for this automation account
do {
    $AzAutomationAccountname = Read-Host -Prompt "Enter the name of the Automation Account"
    if ($AzAutomationAccountname -notmatch '^[a-zA-Z][-a-zA-Z0-9]{4,48}[a-zA-Z0-9]$') {
        Write-Host "Invalid name! Please follow these rules:" -ForegroundColor Red
        Write-Host "- Must be 6-50 characters long"
        Write-Host "- Must start with a letter"
        Write-Host "- Must end with a letter or number"
        Write-Host "- Can contain letters, numbers, and hyphens"
        Write-Host "Please try again." -ForegroundColor Yellow
    }
} while ($AzAutomationAccountname -notmatch '^[a-zA-Z][-a-zA-Z0-9]{4,48}[a-zA-Z0-9]$')


do {
    $AzAutomationAccountLocation = Read-Host -Prompt "Enter the location of the Automation Account"
    $validLocations = (Get-AzLocation).Location
    if ($AzAutomationAccountLocation -notin $validLocations) {
        Write-Host "Invalid location! Please enter one of these Azure locations:" -ForegroundColor Red
        $validLocations | Sort-Object | ForEach-Object { Write-Host "- $_" }
        Write-Host "Please try again." -ForegroundColor Yellow
    }
} while ($AzAutomationAccountLocation -notin $validLocations)


do {
    $AzAutomationAccountResourceGroupName = Read-Host -Prompt "Enter the name of the Resource Group for the Automation Account"
    $validResourceGroups = (Get-AzResourceGroup).ResourceGroupName
    if ($AzAutomationAccountResourceGroupName -notin $validResourceGroups) {
        Write-Host "Invalid Resource Group! Please enter one of these existing Resource Groups:" -ForegroundColor Red
        $validResourceGroups | Sort-Object | ForEach-Object { Write-Host "- $_" }
        Write-Host "Please try again." -ForegroundColor Yellow
    }
} while ($AzAutomationAccountResourceGroupName -notin $validResourceGroups)


do {
    Write-Host "Choose the Automation Account plan:"
    Write-Host "1. Basic"
    Write-Host "2. Free"
    $choice = Read-Host -Prompt "Enter your choice (1 or 2)"
    
    switch ($choice) {
        "1" { $AzAutomationAccountplan = "Basic" }
        "2" { $AzAutomationAccountplan = "Free" }
        default {
            Write-Host "Invalid choice! Please enter either 1 or 2" -ForegroundColor Red
            Write-Host "Please try again." -ForegroundColor Yellow
        }
    }
} while ($choice -notin "1","2")


$AzAutomationAccountAssignSystemIdentity = Read-Host -Prompt "Do you want to assign a system identity to the Automation Account? (Y/N)"
if ($AzAutomationAccountAssignSystemIdentity -eq "Y" -or $AzAutomationAccountAssignSystemIdentity -eq "y") {
    $AzAutomationAccountAssignSystemIdentity = $true
} elseif ($AzAutomationAccountAssignSystemIdentity -eq "N" -or $AzAutomationAccountAssignSystemIdentity -eq "n") {
    $AzAutomationAccountAssignSystemIdentity = $false
} else {
    Write-Host "Invalid input! Defaulting to No." -ForegroundColor Red
    $AzAutomationAccountAssignSystemIdentity = $false
}

Write-Host "`nReview your selections:" -ForegroundColor Cyan
Write-Host "Automation Account Name: $AzAutomationAccountname"
Write-Host "Location: $AzAutomationAccountLocation"
Write-Host "Resource Group: $AzAutomationAccountResourceGroupName"
Write-Host "Plan: $AzAutomationAccountplan"
Write-Host "System Identity: $(if ($AzAutomationAccountAssignSystemIdentity) { 'Yes' } else { 'No' })"

$confirm = Read-Host -Prompt "`nDo you want to proceed with these settings? (Y/N)"
if ($confirm -ne 'Y' -and $confirm -ne 'y') {
    Write-Host "Operation cancelled by user." -ForegroundColor Yellow
    exit
}


if ($AzAutomationAccountAssignSystemIdentity) {
    New-AzAutomationAccount -Name $AzAutomationAccountname -Location $AzAutomationAccountLocation -ResourceGroupName $AzAutomationAccountResourceGroupName -Plan $AzAutomationAccountplan -AssignSystemIdentity
} else {
    New-AzAutomationAccount -Name $AzAutomationAccountname -Location $AzAutomationAccountLocation -ResourceGroupName $AzAutomationAccountResourceGroupName -Plan $AzAutomationAccountplan
}

Azure Automation Accounts are an essential part of a smart cloud strategy. By leveraging them, IT professionals can reduce overhead, improve reliability, and maintain control over sprawling environments.

Whether you’re managing a handful of VMs or an enterprise-grade hybrid infrastructure, automation is your silent workhorse and Azure makes it incredibly approachable.

Thank you for stopping by. ✌️

Azure Role-Based Access: Who’s Got the Keys to the Cloud Castle?

Alright, let’s talk about Azure Role-Based Access Control (RBAC)—the bouncer at the club, the gatekeeper of your cloud kingdom, the difference between “Oops, I deleted the production database” and “Phew, good thing I didn’t have permission for that.”

If you’re working with Microsoft Azure, RBAC is a must-know. It’s how you control who can do what in your cloud environment. Let’s break it down in a fun, easy-to-digest way.

What is Azure RBAC, and Why Should You Care?

Think of Azure RBAC like a high-tech office building with keycards. Not everyone should have access to every room, right? Your interns shouldn’t be able to access the CEO’s private office, and the janitor doesn’t need the nuclear launch codes.

RBAC works the same way in Azure:

  • You assign roles to users, groups, or applications instead of just giving them full access.
  • It’s based on the principle of least privilege, meaning people only get access to what they need—nothing more, nothing less.
  • It prevents chaos. Because let’s be real, one accidental click from an over-permissioned user can lead to disaster.

The Three Key Pieces of RBAC

Azure RBAC is built on three main pieces:

  1. Roles: These define what someone can do. Examples:
    • Owner – The boss. Can do anything and everything.
    • Contributor – Can create and manage resources but can’t assign roles.
    • Reader – Can look, but not touch.
    • Custom Roles – If the built-in roles aren’t enough, you can create your own.
  2. Scope: This defines where the role applies. It can be at:
    • Subscription level (the whole kingdom)
    • Resource group level (a city inside the kingdom)
    • Specific resources (a single castle or shop)
  3. Assignments: This is the who gets what role part. Assign a user, group, or service principal to a role at a given scope, and boom—permissions granted.

Real-World Example: The Coffee Shop Analogy

Imagine you’re running a coffee shop:

  • The Owner (you) can do everything—order supplies, hire staff, make coffee, or even shut down the store.
  • The Baristas (contributors) can make coffee and manage the store but can’t hire or fire anyone.
  • The Customers (readers) can look at the menu, enjoy their coffee, but they’re not allowed behind the counter.

That’s Azure RBAC in action. Everyone gets access to what they need, but no one is accidentally pressing the “shutdown entire store” button.

Common RBAC Mistakes (And How to Avoid Them)

  1. Giving Everyone Owner or Contributor Roles – That’s like handing out master keys to your entire office. Keep permissions minimal!
  2. Not Using Groups – Assigning roles individually? Big mistake. Use Azure AD groups to manage permissions efficiently.
  3. Ignoring Scope – Always assign roles at the lowest necessary level to avoid over-permissioning.
  4. Forgetting to Review Roles Regularly – People leave jobs, projects change, and roles should be updated accordingly.

Final Thoughts: Lock It Down, But Keep It Practical

Azure RBAC is all about control, security, and making sure the right people have the right access. It’s not just an IT thing—it’s about keeping your cloud environment safe and sane.

So next time you’re setting up roles in Azure, ask yourself:

  • Does this person really need this level of access?
  • Could I use a lower scope?
  • Am I following best practices?

Get it right, and your cloud stays secure. Get it wrong, and… well, let’s just say you don’t want to be the person who accidentally gives the intern the power to delete the company’s entire infrastructure.

Thank you for stopping by.✌

How to Automatically Download and Use Azure Public IP Ranges with PowerShell

If you work with firewalls, proxies, or any system that restricts traffic based on IP addresses, you’re likely familiar with the challenges of maintaining access to dynamic cloud infrastructure. Microsoft understands this, which is why they publish the Azure IP Ranges and Service Tags – Public Cloud dataset — a JSON file containing up-to-date IP address ranges used by Azure services.

Why Microsoft Publishes Azure IP Ranges

Microsoft Azure’s cloud infrastructure spans global data centers, with thousands of services running behind constantly shifting sets of IP addresses. To help organizations:

  • Configure firewalls and security appliances
  • Whitelist Azure service IPs
  • Meet compliance or policy needs
  • Route traffic appropriately

…Microsoft provides this public JSON file that includes IP ranges tied to Service Tags like Storage, Sql, AppService, and many others, broken down by region.

If you are using Azure Firewall, then you can use these service tags directly in your firewall rules. More information can be found here. If you are using some other firewall, then you need to check if they support service tags directly e.g., Palo Alto Networks & External Dynamic Lists (EDL).

If you don’t have support for service tags in your firewall, then you need to use IP address prefixes directly. This is not ideal, since you need to update your firewall rules every time when new IP address prefixes are added or removed. This is why automating this process is important.


How Often Is the Data Updated?

Microsoft typically updates the Azure IP Ranges and Service Tags – Public Cloud file weekly, usually every Monday. Updates can reflect:

  • New IPs added for expanding infrastructure
  • Old ranges removed or reallocated
  • Changes to service or region mappings

Each release includes a "changeNumber" field and a "version" field to help you detect updates. Automation is key here — hence the script!


Changes, Changes…

Azure public IP addresses can change weekly! What does that mean for us?

Every week, there may be new IP addresses added to the list. Others may be removed if they’re no longer in use by Azure.

Why does that matter?

Let’s say an on-prem application needs access to an AzureSQL database, you previously added its IPs to your firewall allow-list. Then Azure updates its IP ranges, and the on-prem application keeps using the same IP or IP ranges that’s not in your allow-list. Boom — access denied. Not because you intended to block it, but because you didn’t know about the change.

It’s not just about adding the new IPs. You also need to handle removals to prevent your allow-lists from becoming bloated and insecure.

This isn’t a new problem in networking. But in Azure, the pace of change is faster — often weekly — and automation becomes essential.


How Is the JSON File Structured?

The JSON file is well-organized and structured to support automation. Here’s what it generally looks like:

jsonCopyEdit{
  "changeNumber": 20250401,
  "cloud": "Public",
  "values": [
    {
      "name": "AppService.WestUS",
      "id": "AppService.WestUS",
      "properties": {
        "region": "westus",
        "platform": "Azure",
        "systemService": "AppService",
        "addressPrefixes": [
          "13.64.0.0/18",
          "40.112.0.0/16"
        ]
      }
    },
    ...
  ]
}

Key fields:

  • values: Array of service tag entries
  • name / id: Service and region
  • properties.addressPrefixes: List of IP ranges (in CIDR format)

You can easily filter entries by region, service tag, or even specific prefixes depending on your needs.


Common Use Cases for Downloading Azure IPs

There are many real-world situations where access to this list is helpful:

  • Firewall Whitelisting: Allow only Azure Storage or Sql service traffic from a specific region.
  • Cloud Egress Policies: Identify what your workloads are connecting to by cross-referencing logs with Azure-owned IPs.
  • Network Audits & Compliance: Ensure your infrastructure is only communicating with approved external services.
  • CDN or WAF Configurations: Enable access to Azure Front Door, App Service, or other endpoints behind the scenes.
  • Automation Pipelines: Pull the list programmatically during CI/CD to dynamically configure network security settings.

PowerShell Script to Download the File

To help automate this process, I wrote a PowerShell script that downloads the latest Azure IP Ranges JSON file:

What this script does,

  • Fetches the HTML content of the page https://www.microsoft.com/en-us/download/details.aspx?id=56519 using Invoke-WebRequest.
  • Extracts the JSON file URL from the page content using a regex match.
  • Creates a folder named json_files if it does not already exist.
  • Extracts the JSON file name from the URL and constructs the file path within the json_files folder.
  • Checks if the JSON file already exists:
    • If it exists, skips the download.
    • If it does not exist, downloads the JSON file to the json_files folder.
  • Parses the downloaded JSON file into a PowerShell object using ConvertFrom-Json.
  • Creates a timestamped folder named AzureServicetags_<timestamp> in the directory called ‘AzureServicetags’ in the current directory.
  • Creates three subfolders within the timestamped folder:
    • All_IPs for all IP addresses.
    • IPv4_IPs for IPv4 addresses.
    • IPv6_IPs for IPv6 addresses.
  • Iterates through each service tag in the JSON content:
    • Extracts the service name and its associated IP address prefixes.
    • Separates the IP addresses into IPv4 and IPv6 categories using regex matching.
    • Creates text files for:
      • All IP addresses.
      • IPv4 addresses.
      • IPv6 addresses.
    • Writes the respective IP addresses into the corresponding text files.
    • Outputs a message indicating the creation of files for each service.
  • Skips services that do not have valid address prefixes and outputs a warning message.
  • Outputs a message if the JSON URL is not found.
# Define the URL of the download page
$pageUrl = "https://www.microsoft.com/en-us/download/details.aspx?id=56519"

# Fetch the page source
$response = Invoke-WebRequest -Uri $pageUrl -UseBasicParsing

# Extract the JSON URL for 'url'
$jsonUrl = ($response.Content -match '"url":"(https://download\.microsoft\.com/download/[^"]+)"') | Out-Null
$jsonUrl = $matches[1]

# Output the JSON URL
if ($jsonUrl) {
    Write-Output "JSON URL: $jsonUrl"

    # Create the folder 'json_files' if it doesn't exist
    $jsonFolder = "json_files"
    if (-not (Test-Path -Path $jsonFolder)) {
        New-Item -ItemType Directory -Path $jsonFolder | Out-Null
    }

    # Extract the file name from the JSON URL
    $jsonFileName = $jsonUrl.Split("/")[-1]
    $jsonFilePath = Join-Path -Path $jsonFolder -ChildPath $jsonFileName

    # Check if the JSON file already exists
    if (Test-Path -Path $jsonFilePath) {
        Write-Output "File '$jsonFileName' already exists. Skipping download."
    }
    else {
        # Download the JSON file into the 'json_files' folder
        Invoke-WebRequest -Uri $jsonUrl -OutFile $jsonFilePath
        Write-Output "Downloaded JSON file: $jsonFileName"
    }

    # Parse the JSON file
    $jsonContent = Get-Content -Path $jsonFilePath -Raw | ConvertFrom-Json

    # Create a folder with the current date and time stamp
    $timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm"
    $folderName = ".\AzureServicetags\AzureServicetags_$timestamp"
    New-Item -ItemType Directory -Path $folderName | Out-Null

    # Create subfolders for All_IPs, IPv4_IPs, and IPv6_IPs
    $allIPsFolder = Join-Path -Path $folderName -ChildPath "All_IPs"
    $ipv4Folder = Join-Path -Path $folderName -ChildPath "IPv4_IPs"
    $ipv6Folder = Join-Path -Path $folderName -ChildPath "IPv6_IPs"

    foreach ($subFolder in @($allIPsFolder, $ipv4Folder, $ipv6Folder)) {
        if (-not (Test-Path -Path $subFolder)) {
            New-Item -ItemType Directory -Path $subFolder | Out-Null
        }
    }

    # Iterate through each service tag and create text files
    foreach ($service in $jsonContent.values) {
        $serviceName = $service.name

        if ($service -and $service.properties -and $service.properties.addressPrefixes) {
            $ipAddresses = $service.properties.addressPrefixes
            $ipv4Addresses = $ipAddresses | Where-Object { $_ -match '\.' -and $_ -notmatch '\:' }
            $ipv6Addresses = $ipAddresses | Where-Object { $_ -match '\:' }

            # Create files for all IPs, IPv4 IPs, and IPv6 IPs
            $allIPsFilePath = Join-Path -Path $allIPsFolder -ChildPath "$serviceName`_all_IPs.txt"
            $ipv4FilePath = Join-Path -Path $ipv4Folder -ChildPath "$serviceName`_v4_IPs.txt"
            $ipv6FilePath = Join-Path -Path $ipv6Folder -ChildPath "$serviceName`_v6_IPs.txt"

            $ipAddresses | Out-File -FilePath $allIPsFilePath -Encoding UTF8
            $ipv4Addresses | Out-File -FilePath $ipv4FilePath -Encoding UTF8
            $ipv6Addresses | Out-File -FilePath $ipv6FilePath -Encoding UTF8

            Write-Output "Created files for service: $serviceName"
        }
        else {
            Write-Warning "Service '$serviceName' does not have valid address prefixes. Skipping."
        }
    }
}
else {
    Write-Output "JSON URL not found."
}

Thanks for stopping by. ✌

Azure – Using KeyVault with PowerShell – Updated

Azure Key Vault is used to safely manage Secrets, Certificates and Crytographic Keys used by cloud and on-premise applications. After the secrets are stored in Azure Key Vault, we can assign access policies to user accounts or SPNs to retrieve and use them.

In this post, I will cover,

  • How to create Azure Key Vault
    • Create and update secrets in Azure Key Vault
  • Create a new Azure AD application and SPN
    • Create a client Secret
  • Assign a policy in Azure Key Vault to allow access to the SPN we create
  • Store the Azure AD application ID and client secret in the SecretStore vault
  • Retrieve Secret from Azure Key vault using credentials stored in SecretStore vault

I’ll go through the steps in both the portal and via PowerShell.

Before proceeding further, make sure you are connected to Azure AD and Azure via PowerShell. You may or may not use the same global admin account to connect to both Azure AD and Azure, either way you can use the below cmdlets and adjust it accordingly where necessary.

$AzureADcred = Get-Credential
Connect-AzureAD -credential $AzureADcred
$Azcred = Get-Credential
$SubsName = Read-Host "Enter Azure Subscription Name"
Connect-AzAccount -Credential $Azcred -Subscription $SubsName

Azure Key Vault

Register Resource Provider

Using PowerShell

Use below cmdlet to register ‘Microsoft.KeyVault‘ as a resource provider in the subscription,

Register-AzResourceProvider -ProviderNamespace "Microsoft.KeyVault"

To confirm the registration is successful,

Get-AzResourceProvider | Where-Object {$_.ProviderNamespace -contains "Microsoft.KeyVault"} | select ProviderNamespace, RegistrationState

Using Azure Portal

  1. Login to Azure Portal (https://portal.azure.com/)
  2. Navigate to Subscriptions
  3. Click to select the desired Subscription
  4. In the left navigation menu, click on Resource providers
  5. Search for Microsoft.KeyVault
  6. Click on Microsoft.KeyVault
  7. Click Register
  8. Once complete, Status column for Microsoft.KeyVault will show Registered
Register Resource provider – Microsoft.KeyVault

Create Azure Key Vault

Using PowerShell

To proceed further, launch PowerShell as admin and install the Az.KeyVault PowerShell Module

Install-Module -Name Az.KeyVault

The New-AzKeyVault can be used to create a new Key Vault in Azure. To determine the locations where Key Vault is offered, use the below cmdlet,

Get-AzLocation | Where-Object {$_.Providers -contains "Microsoft.KeyVault"} | ft

Use the below cmdlets to create a new Key Vault,

$kvName = Read-Host "Enter a name for Key Vault"
$rg = Read-Host "Enter Resource Group Name"
$loc = Read-Host "Enter Azure location"
New-AzKeyVault -VaultName $kvName -ResourceGroupName $rg -Location $loc

To confirm Key Vault creation,

Get-AzKeyVault

Using Azure Portal

To cerate a new Key Vault from the Azure portal,

  1. Login to Azure Portal (https://portal.azure.com/)
  2. Search for key vault
  3. Click Create or Create key vault
  4. Provide below information,
    • Subscription
    • Resource group
    • Key vault name
    • Region
    • Pricing tier
  5. Leave the other options default and click Review + create
    • The other options in the creation steps,
      • Access policy = I’ll go through it later in this post
      • Networking = All networks to make it publicly accessible
      • Tags = As necessary

Below are my settings,

Create a key vault

Create SPN in Azure AD

In this step, we’re creating a service principal in Azure AD. We will assign permissions for this SP to retrieve secrets from the Azure Key vault in later step.

In Azure AD, the application registration is the template used to create the SP. Also, the SP is what can be authenticated and authorized. Application and SP are associated by Application ID and they differ in it Object ID.

To create a new Azure AD application,

$appname = Read-Host "Enter a name for the Azure AD application"
New-AzureADApplication -DisplayName $appname

To create a service principal,

$appname = Read-Host "Enter name of Azure AD application"
$AppId = (Get-AzureADApplication -Filter "DisplayName eq '$appname'").AppId
New-AzureADServicePrincipal -AccountEnabled $true -AppId $AppId -DisplayName $appname

Create Client Secret

Next, we create a new client secret using the Get-AzureADApplicationPasswordCredential cmdlet,

$appname = Read-Host "Enter Azure AD application name to determine Object ID"
$appObjID = (Get-AzureADApplication -Filter "DisplayName eq '$appname'").Objectid
$KeyId = Read-Host "Enter value for secret identifier"
New-AzureADApplicationPasswordCredential -ObjectId $appObjID -CustomKeyIdentifier $KeyId

Copy the value in the output to a notepad as I have highlighted above. This value will not be available to copy later.

Assign Permissions

Using PowerShell

We can assign necessary permissions to the Azure AD application we created in above step, using the Set-AzKeyVaultAccessPolicy cmdlet,

$appname = Read-Host "Enter Azure AD application name to determine Object ID"
$Appid = (Get-AzureADApplication -Filter "DisplayName eq '$appname'").AppId
$kvName = Read-Host "Enter a name for Key Vault"
Set-AzKeyVaultAccessPolicy -VaultName $kvName -ServicePrincipalName $Appid -PermissionsToSecrets list,get

Using Azure Portal

  1. Login to Azure Portal (https://portal.azure.com/)
  2. Search for Key vault
  3. Click on the Key Vault we created earlier
  4. In the left navigation menu, click on Access policies
  5. Select Permission model as Vault access policy
  6. Click +Add Access Policy
  7. In the Add access policy window
    • For Secret permissions, select Get and List
    • For Select principal, select the SPN we created earlier
  8. Click Add
  9. Click Save to save policy

Manage Secrets in Key Vault

Applications, scripts or users can create, update, delete and retrieve secrets if they have the necessary policy assigned to them

Creating/Updating Secrets

To create a new secret, we can use the Set-AzureKeyVaultSecret cmdlet,

$Secret = ConvertTo-SecureString -String 'Password' -AsPlainText -Force
$kvName = Read-Host "Enter a name for Key Vault"
$SecName = Read-Host "Enter a name for secret"
Set-AzKeyVaultSecret -VaultName $kvName -Name $SecName -SecretValue $Secret

The secret can be updated to a new value using the same Set-AzureKeyVaultSecret cmdlet,

$Secret = ConvertTo-SecureString -String 'Password' -AsPlainText -Force
$kvName = Read-Host "Enter a name for Key Vault"
$SecName = Read-Host "Enter a name for secret"
$Expires = (Get-Date).AddYears(2).ToUniversalTime()
$NBF =(Get-Date).ToUniversalTime()
$Tags = @{ 'Department' = 'IT'; 'Environment' = 'Production'}
Set-AzKeyVaultSecret -VaultName $kvName -Name $SecName -SecretValue $Secret -Expires $Expires -NotBefore $NBF -Tags $Tags

Retrieving Secrets

To retrieve the current version of a secret, we use the Get-AzureKeyVaultSecret cmdlet,

$kvName = Read-Host "Enter a name for Key Vault"
$SecName = Read-Host "Enter a name for secret"
$secruretext = (Get-AzKeyVaultSecret -VaultName $kvName -Name $SecName).SecretValue

This will assign the stored secret to the $secruretext variable as a SecureString. We can now pass this to any other cmdlets that require a SecureString.

As I’ve already covered the Microsoft.PowerShell.SecretManagement and Microsoft.PowerShell.SecretStore PS modules in an earlier post, I’ll follow on the premise and store the client secret we created in the local vault. This way, I don’t have to save the client secret in the code as plaintext. To do this, we can store the Application ID and Client secret in a PSCredential object to the store,

$credential = Get-Credential
Set-Secret -Name azkv-01 -Secret $credential

In the Windows PowerShell Credential request window, for User Name input the Application (client) ID of the Azure AD application and for password input the Client Secret value we copied into a notepad earlier.

I’ve also created another secret as string in the local vault with my tenant ID value.

Putting this all together, we can use these below lines in PowerShell automation scripts,

$vpwd = (Import-CliXml "C:\Scripts\vpd.xml").Password
Unlock-SecretStore -Password $vpwd
$TenantId = Get-Secret -Vault CredsDB -Name TenantId -AsPlainText
$credential = Get-Secret -Vault CredsDB -Name azkv-01
Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $TenantId

To retrieve the secure string stored in the Azure Key vault, I’m using these lines below. Also for demo purposes, I’m including the -AsPlainText to the Get-AzKeyVaultSecret cmdlet but as I mentioned earlier, we can store this secure string to a variable and pass it on to other cmdlets.

$kvName = Read-Host "Enter a name for Key Vault"
$SecName = Read-Host "Enter a name for secret"
Get-AzKeyVaultSecret -VaultName $kvName -Name $SecName -AsPlainText
#or
$secruretext = (Get-AzKeyVaultSecret -VaultName $kvName -Name $SecName).SecretValue

I know this was a lengthy post and it may have gotten a little confusing right at the end with too many things named vault🤷‍♂️

Hope this helped you out in figuring out in including Azure Key Vault in your PowerShell automations.

Thank you for stopping by ✌

Azure – Integrate Azure AD B2C with ServiceNow

If you aren’t familiar with Azure AD B2C, it is a customer identity access management (CIAM) solution and is a separate service from Azure Active Directory (Azure AD). It is built on the same technology as Azure AD but for a different purpose. It allows businesses to build customer facing applications, and then allow anyone to sign up into those applications with no restrictions on user account. Azure AD B2C uses standards-based authentication protocols including OpenID Connect, OAuth 2.0, and SAML.

In an earlier post, I detailed steps on how to configure ServiceNow with Azure AD SSO. In this post, I will go through steps on how to integrate Azure AD B2C with ServiceNow.

Below is a diagram show the high level implementation steps on how to do this integration,

OpenID Connect (OIDC) is an identity layer built on top of the OAuth protocol, which provides a modern and intuitive Single Sign-on (SSO) experience. ServiceNow supports OIDC to authenticate users in Azure B2C.

I will not cover the Azure AD B2C tenant creation steps in this post.

Create new user flow

A user flow lets us determine how users interact with our application when they do things like sign-in, sign-up, edit a profile, or reset a password.

  1. Sign in to the Azure portal
  2. Make sure you’re using the directory that contains your Azure AD B2C tenant. Select the Directories + subscriptions icon in the portal toolbar
  3. On the Portal settings | Directories + subscriptions page, find your Azure AD B2C directory in the Directory name list, and then select Switch
  4. In the Azure portal, search for and select Azure AD B2C
  5. Under Policies, select User flows, and then select New user flow
  1. On the Create a user flow page, select the Sign up and sign in user flow
  2. Under version, select Recommended, and then select Create
  1. Enter a Name for the user flow. For example, su_si-1
  2. For Identity providers, select Email signup
  3. Under User attributes and token claims, choose the claims and attributes to collect and send from the user during sign-up. Select Show more, and then choose attributes and claims. Click OK. Below screenshot shows the attributes I’m collecting but it is up to you. These attributes can be modified in the user flow at any time
  1. Click Create to add the user flow. A prefix of B2C_1_ is automatically prefixed to the name

Create App Registration

  1. Stay logged into the Azure portal
  2. Make sure you are in the B2C directory
  3. In the left navigation menu, under Manage, Click App registrations, and then select New registration
  4. Enter a Name for the application. For example, ServiceNow
  5. Under Supported account types, select Accounts in any identity provider or organizational directory (for authenticating users with user flows)
  6. Under Redirect URI, select Web then enter your ServiceNow instance with /navpage.do in the URL text box
  7. Under Permissions, select the Grant admin consent to openid and offline_access permissions check box
  8. Click Register

Create a client secret

The client secret is also known as an application password. The secret will be used by ServiceNow to exchange an authorization code for an access token

  1. In the left menu, under Manage, select Certificates & secrets
  2. Click New client secret
  3. Enter a description for the client secret in the Description box. For example, SnowSecret
  4. Under Expires, select a duration for which the secret is valid, and then select Add
    • Note down the secret’s Value for use in ServiceNow. This value is never displayed again after you leave this page

Information needed to configure ServiceNow instance

  1. Click on the Overview, copy the Application (client) ID
  2. Next Click Endpoints
  3. Copy the value in Azure AD B2C OpenID Connect metadata document
  4. Replace with the User flow name we created earlier e.g. B2C_1_su_si-1. Browse to the URL in a Web browser to confirm you have the right URL
  5. You should have these 3 values,
    • Application (client) ID
    • Client Secret Value
    • OIDC well-known endpoint

Configure ServiceNow Instance

Hopefully, you already have SSO enabled in your ServiceNow instance. If not, please refer to this earlier post of mine

  1. Search for multi-provider sso and click Properties
  2. Enable multiple provider SSO
    • You’ll be asked to setup a recovery account
  1. Under Multi-Provider SSO and click Identity Providers
  2. Click New
  3. Click OpenID Connect
  4. In the Import OpenID Connect Well Known Configuration window, provide following information
    • Name = Name of the IdP you wish. Example, B2C
    • Client ID = Application (client) ID from Azure B2C application
    • Client Secret = Client Secret Value we created earlier in the application
    • Well Known Configuration URL = URL we constructed earlier with the policy name
  5. Click Import
  1. Make sure the new IdP is marked Active and Show as Login option is checked
  1. Click on the OIDC Entity tab and click to open the OIDC Entity
  2. Click on OAuth Entity Scopes, double-click on OAuth scope and replace openid with the below value
    • Use your Application (client) ID from B2C app registration
<Application (client) ID> openid offline_access profile email

This OAuth Scope value is required to generate an access token and without that ServiceNow will error out with a missing parameter. I realized this later on based on my research. I initially left it at openid and searching with the error, lead me to this.

  1. Click Update to save changes
  2. Click on OIDC Provider Configuration
  3. Click on OIDC provider value
  1. Update the User Claim to emails
  1. Click Update
  2. To keep things simple, I’m not enabling the Automatic user provisioning option
    • You can choose to enable automatic user provisioning during user login. When automatic user provisioning is enabled, a user record is automatically created in the ServiceNow instance if that user record does not exist.
  3. Back in the Identity provider window, Click Update to save the OIDC Identity Provider values
  4. Navigate to the login page of the instance to verify that IdP appears as a login option
  1. Create a test user in ServiceNow and login with the credentials to test if the IdP configuration works
  2. Optionally you can browse to the login page with the URL in following format,
    • To determine the sys_id, open the OIDC Identity provider we created, right-click on the grey bar and click Copy sys_id
    • Replace this sys_id in the URL below
    • This URL will take you directly to the sign-in page
https://<yourinstance>/login_with_sso.do?glide_sso_id=<sys_id>

Hope this post helped you in setting up your ServiceNow instance with Azure AD B2C.

Thank you for stopping by. ✌