Thanks to visit codestin.com
Credit goes to superwidgets.wordpress.com

Latest

Match-LargeArrays function added to AZSBTools PowerShell module


Sometimes one needs to match large arrays in PowerShell based on a common property. For example, matching Active Directory (AD) users to Azure users based on AD user’s ms-ds-ConsistencyGuid versus Azure user’s ImmutableId. The ImmutableId Azure user property is not actually immutable and can be modified. It is populated with the base 64 version of the corresponding AD user’s ObjectGuid, and is typically populated by the ADConnect software which uses a stripped down version of MIM.

Consider the following demo data:

$DesiredArraySize = 1000
$MatchPerCent = 93.7 # The sample data generated will have x% matching records

#region Generate Demo arrays
$DemoADUserList = $DemoAzureUserList = @()
$MatchRecordCount = [Math]::Round($MatchPerCent * $DesiredArraySize / 100)
foreach ($LoopCounter in (1..$DesiredArraySize)) {
    $Guid = New-Guid
    $EmployeeId = Get-Random -Minimum 1000000000 -Maximum 9999999999
    $DemoADUserList += New-Object -TypeName PSObject -Property ([Ordered]@{
        GivenName                       = 'Sam'
        SurName                         = $Guid
        DisplayName                     = "Sam $Guid"
        Name                            = "Sam $Guid"
        samAccountName                  = "Sam$Guid"
        UserPrincipalName               = "[email protected]"
        Mail                            = "[email protected]"
        EmployeeId                      = $EmployeeId
        Enabled                         = $true
        DistinguishedName               = "CN=Sam $Guid,OU=US,DC=mydomain,DC=com"
        'msDS-CloudExtensionAttribute5' = $EmployeeId
        ObjectGuid                      = $Guid
        'ms-ds-ConsistencyGuid'         = Convert-ObjectGuid2ImmutableId -ObjectGuid $Guid
    })
    if ($LoopCounter -le $MatchRecordCount) {$Id = $Guid} else {$Id = New-Guid}
    $DemoAzureUserList += New-Object -TypeName PSObject -Property ([Ordered]@{
        GivenName         = 'Sam'
        SurName           = $Id
        DisplayName       = "Sam $Id"
        Mail              = "[email protected]"
        UserPrincipalName = "[email protected]"
        AccountEnabled    = $true
        ObjectId          = New-Guid
        ImmutableId       = Convert-ObjectGuid2ImmutableId -ObjectGuid $Id
        CreationType      = $null
        UserState         = $null
        UserType          = 'Member'
    })
}
#endregion

This code generates two array: $DemoADUserList and $DemoAzureUserList. A record in the DemoADUserList looks like:

While a record in the DemoAzureUserList looks like:

Traditional matching algorithm may look like:

#region Match using the traditional method
$Duration  = Measure-Command {
    foreach ($ADUser in $DemoADUserList) {
        if ($FoundInAzure = $DemoAzureUserList | where ImmutableId -EQ $ADUser.'ms-ds-ConsistencyGuid') {
            $ADUser | Add-Member -MemberType NoteProperty -Name MatchingAzureObjectId -Value $FoundInAzure.ObjectId -Force
        } else {
            $ADUser | Add-Member -MemberType NoteProperty -Name MatchingAzureObjectId -Value 'Not Found in Azure' -Force
        }
    }
}
Write-log 'Using the traditional method','matched',('{0:N0}' -f $DesiredArraySize),'lists',"($('{0:N0}' -f ($DesiredArraySize*$DesiredArraySize)) records) in",
    "$($Duration.Hours):$($Duration.Minutes):$($Duration.Seconds)",'hh:mm:ss',"($('{0:N0}' -f $Duration.TotalSeconds) seconds)" Yellow,Green,Cyan,Green,Cyan,Green,Cyan,DarkYellow
Write-Log '   Identified',('{0:N0}' -f ($DemoADUserList | where MatchingAzureObjectId -ne 'Not Found in Azure').Count),'matching records' Green,Cyan,Green
#endregion

The problem with traditional matching algorithm is that it takes a very long time for large data sets. For example, for 10k records data sets, this algorithm takes ~ 30 minutes. For 200k data sets, it takes over a week!!

The new Match-LargeArrays function leverages Hashtable indexing to reduce that matching time by upwards of 50,000% or 500 folds!!

$Result = Match-LargeArrays -Array1 $DemoADUserList -Property1 'ms-ds-ConsistencyGuid' -Array2 $DemoAzureUserList -Property2 'ImmutableId'

For a 200k data sets the matching time is reduced from over a week to under 2 minutes!!

The result for 10k data sets takes under 2 seconds:

Using the traditional matching algorithm with the same 10k data sets and on the same hardware takes 17 minutes and 31 seconds or over 586 times longer!!

The $Result is the function’s returned array. It is a copy of the input Array1 with an additional property “MatchingObject” that contains the matching record(s) from Array2. For example:


To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show

UnGzip-File function added to AZSBTools PowerShell module to decompress GZip files in Windows


Microsoft provides the Expand-Archive cmdlet as part of the Microsoft.PowerShell.Archive module to decompress ZIP files in Windows. However, there’s no native cmdlet to decompress GZip files.

This new function of the AZSBTools module leverages native .Net 2.0 libraries to decompress GZip files in Windows.

The function’s built in help can be shown using

help UnGZip-File -ShowWindow

Here’s a demo of using this function:

# Demo UnZip-File

# Input
$FolderPath = 'c:\Sandbox\pfSense'
$URL        = 'https://atxfiles.netgate.com/mirror/downloads/pfSense-CE-2.6.0-RELEASE-amd64.iso.gz'

# Download the GZ file into the $FolderPath
$GZFilePath = Join-Path $FolderPath (Split-Path $URL -Leaf) # Concatenate the $FolderPath with the file name
Invoke-WebRequest -Uri $URL -OutFile $GZFilePath

# Decompress the GZ (GZIP) file using the new UnGzip-File function
UnGZip-File -GzFile $GZFilePath -OutFile ($GZFilePath -replace '.gz','') -ShowProgress

In the PowerShell ISE, you should see the download progress like:

Followed by the decompression progress like:

Warning:

Using the -ShowProgress switch will SIGNIFICANTLY slow down the decompression process. It is not recommended to use this switch with large files.

At the end, the function displays decompression stats to the console like:

The same can be seen in Windows Explorer:


To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show

Deploy Django Web App that uses SQLite to Azure


Django is a commonly used high-level Python web framework. This post goes over the steps to deploy Django Web App that uses SQLite to Azure.

Prepare your Settings.py

In your Settings.py file, configure the following variables to take their values from the corresponding environment variables, as in:

ALLOWED_HOSTS is configured to allow subdomain wildcard .azurewebsites.net which is the default URL prefix for Azure Web Apps. This is important for host header validation to prevent host header forgery and attacks.

Make sure you have import os at the top of your Settings.py file.

Create Azure Web App

In the Azure Portal, create a resource:

Click Create under Web App

  • Pick or create a Resource Group
  • Type in a name for your Web App
  • Pick Python 3.10 for the Runtime stack
  • Pick an Azure Region – typically that should be geographically close to the majority of the App users
  • Pick or create a new pricing plan that includes “Basic B1” or better as shown below. Basic B1 is the cheapest plan that supports GitHub integration and “continuous deployment”

Click “Review + create”. Do not go to the Deployment tab. This is important at this step. We need to configure the App’s “Application Settings” before we enable GitHub integration. “Application Settings” are exposed as environment variables for access by the Web App at runtime.

Keep the rest of the defaults. Your deployment should look like:

Configure the Web App’s “Application Settings”

“Application Settings” are exposed as environment variables for access by the Web App at runtime.

Under the App’s Configuration/Application settings, click “New application setting”

Add a variable called SECRET_KEY with a value like:

Add DEBUG variable:

You can come back and change that to False later.

These correspond to the Settings.py environment variable we setup earlier

Also setup SCM_DO_BUILD_DURING_DEPLOYMENT variable with value of 1.

Connect to source control

Now connect the Web App to the GitHub source code:

and Save:

Watch Deployment Center Logs for deployment progress:

Note:

The Azure Web App Deployment Center will watch for any code changes and automatically pull them:

Setup the database

Next, go to the SSH web console at https//<appname>.scm.azurewebsites.net/webssh/host

To setup the database, invoke:

python manage.py migrate

To set up the Database Models in models.py, invoke:

python manage.py makemigrations
python manage.py migrate

That’s it!

Now browse to the Web App like <myApp>.azurewebsites.net/

Update-GoogleImageCreationTimeStamp function added to AZSBTools PowerShell module


Google offers a “takeout service” at https://takeout.google.com/ where you can select different types of your Google account data to download as a single ZIP file for example. If you download your pictures from your Google account, you’ll get a file like:

When you unzip the file, you’ll get the image files and corresponding metadata files in JSON format like:

The JSON files will look like:

Notice that the unzipped image file has the time stamp of when the image was zipped by Google in the “Google Takeout” process, not the actual date/time when the image was taken.

The JSON metadata corresponding file provides 3 different time stamps related to the image:

  • creationTime
  • photoTakenTime
  • photoLastModifiedTime

The Update-GoogleImageCreationTimeStamp function of the AZSBTools PowerShell module provides the ability to set the image time stamp to any of the 3 time stamps available in the corresponding JSON file.

Here’s an example of a list of unzipped files from Google takeout of photo files:

To change the image files date time, we can use:

(Get-ChildItem '.\' -Include '*.jpg' -Recurse).FullName | foreach { Update-GoogleImageCreationTimeStamp -ImageFileFullPath $_ }

We see console output like:

The error messages are about the ‘-edited’ files because they have no corresponding JSON files. This behavior is by design. Now the image files look like:

Note that the “Date” time stamp accurately reflects the “photoTakenTime” shown in the corresponding JSON file.

The “Date” time shown in Windows Explorer is the “CreationTime” file attribute. The “LastAccessTime” and “LastWriteTime” file attributes are not changed.

Next I delete the JSON files and the LOG files:

Get-ChildItem '.\' -Include '*.log','*.JSON' -Recurse | Remove-Item -Force 

The ‘-edited’ files contain additional internal Google “Picasa” metadata and can be deleted.

Finally, I delete the ‘-Edited’ files:

Get-ChildItem '.\' -Include '*.jpg' -Recurse | where Name -Match '-edited.jpg' | Remove-Item -Force

And now we’re left with the desired pictures with their original time stamps:


To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show

Using Azure API for Python in PyCharm


One time computer preparation

Install the Azure library packages:

  • Prepare a “requirements” file
    In this demo, we will name it “AzReq1.txt” with content that looks like:
azure-mgmt-resource>=18.0.0
azure-identity>=1.5.0              
  • install the requirements. In PyCharm, open a Terminal (ALT-F12) and invoke:
pip install -r AzReq1.txt

You’ll see output similar to:


Collecting azure-mgmt-resource>=18.0.0
  Downloading azure_mgmt_resource-21.1.0-py3-none-any.whl (1.8 MB)
     |████████████████████████████████| 1.8 MB 939 kB/s
Collecting azure-identity>=1.5.0
  Downloading azure_identity-1.10.0-py3-none-any.whl (134 kB)
     |████████████████████████████████| 134 kB 3.3 MB/s
Collecting azure-mgmt-core<2.0.0,>=1.3.0
  Downloading azure_mgmt_core-1.3.2-py3-none-any.whl (26 kB)
Collecting azure-common~=1.1
  Downloading azure_common-1.1.28-py2.py3-none-any.whl (14 kB)
Collecting msrest>=0.6.21
  Downloading msrest-0.7.1-py3-none-any.whl (85 kB)
     |████████████████████████████████| 85 kB 1.2 MB/s
Collecting cryptography>=2.5
  Downloading cryptography-38.0.1-cp36-abi3-win_amd64.whl (2.4 MB)
     |████████████████████████████████| 2.4 MB 3.3 MB/s
Collecting msal<2.0.0,>=1.12.0
  Downloading msal-1.18.0-py2.py3-none-any.whl (82 kB)
     |████████████████████████████████| 82 kB 6.1 MB/s
Collecting msal-extensions<2.0.0,>=0.3.0
  Downloading msal_extensions-1.0.0-py2.py3-none-any.whl (19 kB)
Collecting six>=1.12.0
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting azure-core<2.0.0,>=1.11.0
  Downloading azure_core-1.25.1-py3-none-any.whl (178 kB)
     |████████████████████████████████| 178 kB 3.2 MB/s
Collecting requests>=2.18.4
  Downloading requests-2.28.1-py3-none-any.whl (62 kB)
     |████████████████████████████████| 62 kB 571 kB/s
Collecting typing-extensions>=4.0.1
  Downloading typing_extensions-4.3.0-py3-none-any.whl (25 kB)
Collecting cffi>=1.12
  Downloading cffi-1.15.1-cp310-cp310-win_amd64.whl (179 kB)
     |████████████████████████████████| 179 kB 3.2 MB/s
Collecting PyJWT[crypto]<3,>=1.0.0
  Downloading PyJWT-2.4.0-py3-none-any.whl (18 kB)
Collecting portalocker<3,>=1.6
  Downloading portalocker-2.5.1-py2.py3-none-any.whl (15 kB)
Collecting requests-oauthlib>=0.5.0
  Downloading requests_oauthlib-1.3.1-py2.py3-none-any.whl (23 kB)
Collecting isodate>=0.6.0
  Downloading isodate-0.6.1-py2.py3-none-any.whl (41 kB)
     |████████████████████████████████| 41 kB 59 kB/s
Collecting certifi>=2017.4.17
  Downloading certifi-2022.6.15-py3-none-any.whl (160 kB)
     |████████████████████████████████| 160 kB ...
Collecting pycparser
  Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)
     |████████████████████████████████| 118 kB 6.4 MB/s
Collecting pywin32>=226
  Downloading pywin32-304-cp310-cp310-win_amd64.whl (12.1 MB)
     |████████████████████████████████| 12.1 MB ...
Collecting charset-normalizer<3,>=2
  Downloading charset_normalizer-2.1.1-py3-none-any.whl (39 kB)
Collecting urllib3<1.27,>=1.21.1
  Downloading urllib3-1.26.12-py2.py3-none-any.whl (140 kB)
     |████████████████████████████████| 140 kB ...
Collecting idna<4,>=2.5
  Downloading idna-3.3-py3-none-any.whl (61 kB)
Collecting oauthlib>=3.0.0
     |████████████████████████████████| 151 kB 6.4 MB/s
Installing collected packages: pycparser, cffi, urllib3, PyJWT, idna, cryptography, charset-normalizer, certifi, typing-extensions, six, requests, pywin32, oauthlib, requests-oauthlib, portalocker, msal, isodate, azure-core, msrest, msal-extensions, azure-mgmt-core, azure-common, azure-mgmt-resource, azure-identity

Successfully installed PyJWT-2.4.0 azure-common-1.1.28 azure-core-1.25.1 azure-identity-1.10.0 azure-mgmt-core-1.3.2 azure-mgmt-resource-21.1.0 certifi-2022.6.15 cffi-1.15.1 charset-normalizer-2.1.1 cryptography-38.0.1 idna-3.3 isodate-0.6.1 msal-1.18.0 msal-extensions-1.0.0 msrest-0.7.1 oauthlib-3.2.0 portalocker-2.5.1 pycparser-2.21 pywin32-304 requests-2.28.1 requests-oauthlib-1.3.1 six-1.16.0 typing-extensions-4.3.0 urllib3-1.26.12

Session preparation – login to Azure tenant

In PyCharm, open a Terminal (ALT-F12) and invoke:

az login

Follow the instructions like:

To sign in, use a web browser to open the page 
https://microsoft.com/devicelogin and enter the code ABCDEFGHI to authenticate.

After login you’ll see Terminal output like

[
    {
        "cloudName": "AzureCloud",
        "id": "12341234-1234-1234-1234-123412341234",
        "isDefault": true,
        "name": "Sam something",
        "state": "Enabled",
        "tenantId": "12341234-1234-1234-1234-123412341234",
        "user": {
            "name": "[email protected]",
            "type": "user"
        }
    }
]

Provision and modify a Resource Group

Create a Python file like

# Import the needed credential and management objects from the libraries.
from azure.mgmt.resource import ResourceManagementClient
from azure.identity import AzureCliCredential

# Input
subscription_id = "12341234-1234-1234-1234-123412341234"
resourcegroup_name = "INF601b"
location = "centralus"
tag_owner = "Sam Boutros"
tag_endoflife = "12/31/2023"

# Acquire a credential object using CLI-based authentication.
credential = AzureCliCredential()

# Obtain the management object for resources.
resource_client = ResourceManagementClient(credential, subscription_id)

# Provision the resource group.
rg_result = resource_client.resource_groups.create_or_update(
    resourcegroup_name,
    {
        "location": location
    }
)
print(f"Provisioned resource group {rg_result.name} in the {rg_result.location} region")

# Update RG, adding tags
rg_result = resource_client.resource_groups.create_or_update(
    resourcegroup_name,
    {
        "location": location,
        "tags": { "owner":tag_owner, "EndOfLife":tag_endoflife }
    }
)
print(f"Updated resource group {rg_result.name} with tags")

Run the file:

We’ll see output like:

We can see the RG in the Azure portal as well:

References

Protected: Welcome


This content is password-protected. To view it, please enter the password below.

Report-AzureServicePrincipals function added to AZSBTools PowerShell module to provide detailed reporting on Service Principals


Service Principals in an Azure tenant are local identities that are not subject to MFA and are often granted wide-ranging pervasive un-scoped API permissions, such as Exchange Online Mailbox : ReadWrite.All : Application, or SharePoint : Sites.FullControl.All : Application.

A Service Principal is a discrete object that’s tightly integrated with an App Registration. This Report-AzureServicePrincipals function provides reporting on Service Principals with emphasis on security relevant properties. It requires the following 3 PowerShell modules:

  • AzureADPreview
  • Microsoft.Graph.Authentication
  • Microsoft.Graph.Applications

First time use will require granting the Graph API permissions ‘User.Read’ and ‘Application.Read.All’.

The Report-AzureServicePrincipals function creates a CSV report. Each record represents a Service Principal/App Registration with the following properties:

DisplayName                              : TemasAutomation1
AppId                                    : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
DateCreated                              : 8/30/2019 1:40:24 PM
AllowPublicClientFlows                   : False
SecretAboutToExpire                      : 
SecretExpired                            : 'Sec1' expired 09/17/2020 14:02:05
SecretAgeTooLong                         :                                         
CertAboutToExpire                        : 
CertExpired                              : 
CertAgeTooLong                           :                                             MultiTenantApp                           : False
AppPublisher                             : mytenant.com
AppDescription                           : 
AppNotes                                 : 
Tags                                     : 
AllowApp2IssueAccessTokens_ImplicitFlows : False
IdTokenAdditionalClaims                  : None
AccessTokenAdditionalClaims              : None
Saml2TokenAdditionalClaims               : None
AdditionalTokenProperties                : None
SecretCredentials                        : Sec1 (KeyId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) (From 17 September 2019 to 17 September 2020 - 1:0 Years:Days)
CertificateCredentials                   : None
APIPermissions                           : Microsoft Graph:User.Read.All:Delegated, Group.ReadWrite.All:Application, 62a82d76-70ea-41e2-9197-370581804d09:Application, df021288-bdef-4463-88db-98f22de89214:Application
Owners                                   : FisrtName LastName ([email protected])
ExposedAPIs                              : user_impersonation (User)               

Notes:

  • SecretAboutToExpire field: shows secrets that expire in the next 90 days. This value is configurable via the SecretWarnDays parameter.
  • CertAboutToExpire field: shows certificates that expire in the next 90 days. This value is configurable via the CertWarnDays parameter.
  • In the SecretAgeTooLong field: Any secret with life span longer than 1 year will show up here – separated by ‘ ##### ‘
  • In the CertAgeTooLong field: Any certificate with life span longer than 2 years will show up here – separated by ‘ ##### ‘
  • In the ExposedAPIs field: ‘User’ means both admins and users can consent. ‘Admin’ means admins only can consent.
  • APIPermissions field: The intent is to show permissions as API Name:Permission Name:Type such as Microsoft Graph:User.ReadWrite.All:Delegated. However, Permission Name is sometimes available as GUID only.

To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show

Get-O365DetailedLicenseReport function added to AZSBTools PowerShell module to provide detailed reporting on O365 license assignments


In a large organization with tens of thousands of Azure users who may or may not need O365 licenses assigned, managing O365 license assignments can be challenging. There are several facts to consider:

  1. O365 license packs are numerous. Microsoft lists over 2,600 service plans:
The supporting Get-O365LicenseReference function provides a link between License name and its ‘friendly’ name

2. Managing or reporting on O365 license assignments via the Azure portal is not adequate for large numbers of users.

3. O365 licenses can be assigned directly, or via Azure group membership.

4. Azure permits multiple O365 license assignments to the same user, even of the same exact license. For example, the same user can be assigned ‘StandardPack’ AKA ‘Office 365 E1’ both as a direct assignment AND via membership in an Azure group configured to grant E1 licenses to its members. It’s unclear whether in this scenario one user consumes 2 E1 licenses or only 1.

5. Some O365 license assignments conflict with one another causing loss of functionality such as loss of access to OneDrive for Business.

6. Some duplicate O365 license assignments can be wasteful. For example, if a user is assigned both an E1 and E3 licenses at the same time. Both are consumed by that single user, wasting the E1 license.

7. PowerShell AzureAD module provides visibility into which license is assigned to which user but lacks the critical information of how that license is assigned. That’s whether a license is obtained via direct assignment or via a specific Azure group membership and which group.

Other than the Azure portal, that critical information of how an O365 license is obtained is exposed only by the MSOnline legacy PowerShell module or from the Graph API.

The new Get-O365DetailedLicenseReport function facilitates the reporting on O365 license assignments leveraging the legacy MSOnline PowerShell module. This function should be preceded by Connect-MsolService cmdlet to obtain an access token for the current PowerShell session. It returns a list of Azure users who have O365 license assignments. Each record has information similar to:

FirstName           : First
LastName            : Last
DisplayName         : Last, First
SignInName          : [email protected]
UserPrincipalName   : [email protected]
UserType            : Member
AssignedLicenses    : ENTERPRISEPACK, EMS
LicenseFriendlyName : Office 365 E3, ENTERPRISE MOBILITY + SECURITY E3
LicenseAssignments  : Direct Assignment, G_AZUREONLY_Win10_Protection

This information can be exported to CSV file and viewed in Ms Excel:

Sample console output of the Get-O365DetailedLicenseReport function
Sample Get-O365DetailedLicenseReport function output viewed in MS Excel

The ‘LicenseFriendlyName’ and ‘LicenseAssignments’ columns provide the desired elusive O365 license assignment details needed to resolve many of the issues noted above such as duplicate wasted O365 license assignments, and conflicting O365 license assignments.


To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show

Decode-String function added to AZSBTools PowerShell module


Decode-String is a function that helps to decode hexadecimal codes often used in URLs and seen in Web server logs. For example %26 would be replaced by &.

Example:

Decode-String -EncodedString '%3CSCRIPT%3Evar+x+%3D+String(%2FXSS%2F)%3Bx+%3D+x.substring(1%2C+x.length-1)%3Balert(x)%3C%2FSCRIPT%3E'
Decode-String Example

The function replaces ‘+’ signs with spaces as in Java Script. Using the -KeepPlus switch reverses this behavior keeping the ‘+’ signs:

Decode-String Example with the -KeepPlus switch

To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable
This image has an empty alt attribute; its file name is sb-tools001.jpg

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show
This image has an empty alt attribute; its file name is get-dayofmonth07.jpg



Get-WinEventLogMetdata function added to AZSBTools PowerShell module


Get-WinEventLogMetdata function returns metadata of one or more Windows Event Logs. Specifically it returns data similar to:

Get-WinEventLogMetdata

The LogTimeSpan property is a calculated property. It is the time between the first and last records in the event log. To see more details, use the -verbose parameter:

Using -Verbose with Get-WinEventLogMetdata

In some environments where domain controllers respond to millions of authentication requests per hour, we may want to track the source of the authentication request load, in terms of IP and user name. This may even exhibit signs similar to Denial of Service, such as resource and RPC port exhaustion. Identifying the source of the authentication load will depend on tracking events like event 4624 in the Security log. The event logs are typically configured in ‘circular’ mode. This means as the log runs out of space, newer events delete older ones. This function helps to point out if the log file size is large enough to allow these events to be captured by a SIEM or a similar central logging and reporting mechanism.

It is not uncommon to see a 132 MB security log get completely written in ~90 seconds showing over 300k events. The maximum size of a Windows event log is 4 GB and is often controlled by GPO (Group Policy).


To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show
Design a site like this with WordPress.com
Get started