• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Clatent

Technology | Fitness | Food

  • About
  • Resources
  • Contact

Documentation

Now you can use your own company standards with Maester custom tests

February 3, 2025 by ClaytonT Leave a Comment

I thought checking to see if they were filled in or even formatted correctly wasn’t enough.. now you can config the validation.json file in the Validating folder with your company standards to make only those values pass. Here are the fields so far, and will be adding more!

  • ENTRA.UV.1001 – Company Name
  • ENTRA.UV.1002 – Street Address
  • ENTRA.UV.1003 – City
  • ENTRA.UV.1004 – State
  • ENTRA.UV.1005 – Postal Code
  • ENTRA.UV.1006 – Country
  • ENTRA.UV.1007 – Business Phone Number
  • ENTRA.UV.1008 – Job Title
  • ENTRA.UV.1009 – Department

Hope you like this new update and let me know if you run into any issues or want to see any other updates. Please don’t forget to star the repo and share to get the word out so more people can add theirs.

Have a great day!

GitHub: Custom Maester Tests
Website: Custom Maester Tests
Website: Offical Maester Website

Tagged With: 365, Automation, Maester, PowerShell, Reporting, Security

If Maester couldn’t get any better…Custom Test Collection now available

January 27, 2025 by ClaytonT Leave a Comment

The time has finally come. I have created a public repository to store custom Maester tests for everyone. As well as a website for deeper understanding where needed. I haven’t seen anyone else do it yet, and worse case scenario, people can just use the ones that I create, but I envision others adding theirs to this too. Yes, you will have to create the function, test, and the markdown file (I and/or others can help), so that we can have a collection of tests that anyone can pick and choose which ones they want to add to their Maester and customize it to their needs. They don’t need to be 365 related either, as they could be checks for Windows 11 settings, server configs, or check that a certain OU should only has these mentioned users or computers and to make sure that doesn’t change.

This is still in its early stages and would love any feedback to make it better while still showing that it is a companion to Maester. I wanted to get the framework started to that we can start gaining the benefits from the repository while still making it easy to use.

I hope you are excited about this as I am, and we can create a large community collection of tests.

Please star and share the repo. Open issues for tests that you want to see and if you already have one or can make it, put that in the issue. Let’s make all our IT lives easier and safer.

Thank you for taking the time to read this and hope you find value in this and can share your knowledge as well.

Website: https://devclate.github.io/Custom-Maester-Tests/
GitHub: https://github.com/DevClate/Custom-Maester-Tests

I’m also working on a module for the Entra attribute fields that will fix any issues by either manually typing in the correct value or only allow company standard values.

Tagged With: 365, AD, Automation, Entra, Maester, PowerShell, Reporting, Windows Server

Simple Tip for GitHub Copilot

September 20, 2024 by ClaytonT 2 Comments

If you have GitHub Copilot, you may or may not know about this little tip, but wanted to let you know just in case. It has saved me so much time and it can be applied to a lot of scenarios.

Here is the prompt, “Can you add the export to markdown capability from #file:Test-365ACCompanyName.ps1 to #file:Test-365ACStreetAddress.ps1”

And what this does is it adds the functionality of exporting to markdown to the new file the same I did in CompanyName, but adapts it to fit StreetAddress. Further more, it adds Help for it and creates the parameter for it(with ValidatePattern).

From this:

<#
.SYNOPSIS
    Tests whether users have a street address and generates a report.

.DESCRIPTION
    The Test-365ACStreetAddress function tests whether users have a street address and generates a report. 
    It takes a list of users as input and checks if each user has a street address. 
    The function generates a report that includes the user's display name and whether they have a street address.
    The report can be exported to an Excel file or an HTML file.

.PARAMETER Users
    Specifies the list of users to test. If not provided, it retrieves all users from the Microsoft Graph API.

.PARAMETER TenantID
    The ID of the tenant to connect to. Required if using app-only authentication.

.PARAMETER ClientID
    The ID of the client to use for app-only authentication. Required if using app-only authentication.

.PARAMETER CertificateThumbprint
    The thumbprint of the certificate to use for app-only authentication. Required if using app-only authentication.

.PARAMETER AccessToken
    The access token to use for authentication. Required if using app-only authentication.

.PARAMETER InteractiveLogin
    Specifies whether to use interactive login. If this switch is present, interactive login will be used. Otherwise, app-only authentication will be used.

.PARAMETER OutputExcelFilePath
    Specifies the file path to export the report as an Excel file. The file must have a .xlsx extension.

.PARAMETER OutputHtmlFilePath
    Specifies the file path to export the report as an HTML file. The file must have a .html extension.

.PARAMETER TestedProperty
    Specifies the name of the property being tested. Default value is 'Has Street Address'.

.EXAMPLE
    Test-365ACStreetAddress -Users $users -OutputExcelFilePath "C:\\Reports\\StreetAddressReport.xlsx"

    This example tests the specified list of users for street addresses and exports the report to an Excel file.

.EXAMPLE
    Test-365ACStreetAddress -OutputExcelFilePath "C:\\Reports\\StreetAddressReport.xlsx"

    This example retrieves all users from the Microsoft Graph API, tests them for street addresses, and exports the report to an Excel file.

#>

Function Test-365ACStreetAddress {
    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeline = $true)]
        [array]$Users = (Get-MgUser -All -Property DisplayName, StreetAddress | Select-Object DisplayName, StreetAddress),
        
        [Parameter(Mandatory = $false)]
        [string]$TenantID,
        
        [Parameter(Mandatory = $false)]
        [string]$ClientID,
        
        [Parameter(Mandatory = $false)]
        [string]$CertificateThumbprint,
        
        [Parameter(Mandatory = $false)]
        [string]$AccessToken,
        
        [Parameter(Mandatory = $false)]
        [switch]$InteractiveLogin,

        [ValidatePattern('\\.xlsx$')]
        [string]$OutputExcelFilePath,
        
        [ValidatePattern('\\.html$')]
        [string]$OutputHtmlFilePath,
        
        [string]$TestedProperty = 'Has Street Address'
    )
    BEGIN {
        if ($InteractiveLogin) {
            Write-PSFMessage "Using interactive login..." -Level Host
            Connect-MgGraph -Scopes "User.Read.All", "AuditLog.read.All"  -NoWelcome
        }
        else {
            Write-PSFMessage "Using app-only authentication..." -Level Host
            Connect-MgGraph -ClientId $ClientID -TenantId $TenantID -CertificateThumbprint $CertificateThumbprint -Scopes "User.Read.All", "AuditLog.Read.All"
        }
        
        $results = @()
    }
    PROCESS {
        foreach ($user in $Users) {
            $hasStreetAddress = [bool]($user.StreetAddress)
            $result = [PSCustomObject]@{
                'User Display Name' = $user.DisplayName
                $TestedProperty     = $hasStreetAddress
            }
            $results += $result
        }
    }
    END {
        $totalTests = $results.Count
        $passedTests = ($results | Where-Object { $_.$TestedProperty }).Count
        $failedTests = $totalTests - $passedTests
        if ($OutputExcelFilePath) {
            Export-365ACResultToExcel -Results $results -OutputExcelFilePath $OutputExcelFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
        }
        elseif ($OutputHtmlFilePath) {
            Export-365ACResultToHtml -Results $results -OutputHtmlFilePath $OutputHtmlFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
        }
        else {
            Write-Output $results
        }
    }
}

To this:

<#
.SYNOPSIS
    Tests whether users have a street address and generates a report.
.DESCRIPTION
    The Test-365ACStreetAddress function tests whether users have a street address and generates a report. 
    It takes a list of users as input and checks if each user has a street address. 
    The function generates a report that includes the user's display name and whether they have a street address.
    The report can be exported to an Excel file, an HTML file, or a Markdown file.
.PARAMETER Users
    Specifies the list of users to test. If not provided, it retrieves all users from the Microsoft Graph API.
.PARAMETER TenantID
    The ID of the tenant to connect to. Required if using app-only authentication.
.PARAMETER ClientID
    The ID of the client to use for app-only authentication. Required if using app-only authentication.
.PARAMETER CertificateThumbprint
    The thumbprint of the certificate to use for app-only authentication. Required if using app-only authentication.
.PARAMETER AccessToken
    The access token to use for authentication. Required if using app-only authentication.
.PARAMETER InteractiveLogin
    Specifies whether to use interactive login. If this switch is present, interactive login will be used. Otherwise, app-only authentication will be used.
.PARAMETER OutputExcelFilePath
    Specifies the file path to export the report as an Excel file. The file must have a .xlsx extension.
.PARAMETER OutputHtmlFilePath
    Specifies the file path to export the report as an HTML file. The file must have a .html extension.
.PARAMETER OutputMarkdownFilePath
    Specifies the file path to export the report as a Markdown file. The file must have a .md extension.
.PARAMETER TestedProperty
    Specifies the name of the property being tested. Default value is 'Has Street Address'.
.EXAMPLE
    Test-365ACStreetAddress -Users $users -OutputExcelFilePath "C:\\Reports\\StreetAddressReport.xlsx"
    This example tests the specified list of users for street addresses and exports the report to an Excel file.
.EXAMPLE
    Test-365ACStreetAddress -OutputExcelFilePath "C:\\Reports\\StreetAddressReport.xlsx"
    This example retrieves all users from the Microsoft Graph API, tests them for street addresses, and exports the report to an Excel file.
#>
Function Test-365ACStreetAddress {
[CmdletBinding()]
param
(
    [Parameter(ValueFromPipeline = $true)]
    [array]$Users = (Get-MgUser -All -Property DisplayName, StreetAddress | Select-Object DisplayName, StreetAddress),
    
    [Parameter(Mandatory = $false)]
    [string]$TenantID,
    
    [Parameter(Mandatory = $false)]
    [string]$ClientID,
    
    [Parameter(Mandatory = $false)]
    [string]$CertificateThumbprint,
    
    [Parameter(Mandatory = $false)]
    [string]$AccessToken,
    
    [Parameter(Mandatory = $false)]
    [switch]$InteractiveLogin,
    
    [ValidatePattern('\\.xlsx$')]
    [string]$OutputExcelFilePath,
    
    [ValidatePattern('\\.html$')]
    [string]$OutputHtmlFilePath,
    
    [ValidatePattern('\\.md$')]
    [string]$OutputMarkdownFilePath,
    
    [string]$TestedProperty = 'Has Street Address'
)
BEGIN {
    if ($InteractiveLogin) {
        Write-PSFMessage "Using interactive login..." -Level Host
        Connect-MgGraph -Scopes "User.Read.All", "AuditLog.read.All"  -NoWelcome
    }
    else {
        Write-PSFMessage "Using app-only authentication..." -Level Host
        Connect-MgGraph -ClientId $ClientID -TenantId $TenantID -CertificateThumbprint $CertificateThumbprint -Scopes "User.Read.All", "AuditLog.Read.All"
    }
    
    $results = @()
}
PROCESS {
    foreach ($user in $Users) {
        $hasStreetAddress = [bool]($user.StreetAddress)
        $result = [PSCustomObject]@{
            'User Display Name' = $user.DisplayName
            $TestedProperty     = $hasStreetAddress
        }
        $results += $result
    }
}
END {
    $totalTests = $results.Count
    $passedTests = ($results | Where-Object { $_.$TestedProperty }).Count
    $failedTests = $totalTests - $passedTests
    if ($OutputExcelFilePath) {
        Export-365ACResultToExcel -Results $results -OutputExcelFilePath $OutputExcelFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
        Write-PSFMessage "Excel report saved to $OutputExcelFilePath" -Level Host
    }
    elseif ($OutputHtmlFilePath) {
        Export-365ACResultToHtml -Results $results -OutputHtmlFilePath $OutputHtmlFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
        Write-PSFMessage "HTML report saved to $OutputHtmlFilePath" -Level Host
    }
    elseif ($OutputMarkdownFilePath) {
        Export-365ACResultToMarkdown -Results $results -OutputMarkdownFilePath $OutputMarkdownFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
        Write-PSFMessage "Markdown report saved to $OutputMarkdownFilePath" -Level Host
    }
    else {
        Write-PSFMessage -Level Output -Message ($results | Out-String)
    }
}
}

And here is the source Test-365ACCompanyName.ps1 code

<#
.SYNOPSIS
Tests if users have a company name property and generates test results.

.DESCRIPTION
The Test-365ACCompanyName function tests if users have a company name property and generates test results. It takes an array of users as input and checks if each user has a company name property. The test results are stored in an array of custom objects, which include the user's display name and the result of the test.

.PARAMETER Users
Specifies the array of users to test. Each user should have a DisplayName and CompanyName property.

.PARAMETER TenantID
The ID of the tenant to connect to. Required if using app-only authentication.

.PARAMETER ClientID
The ID of the client to use for app-only authentication. Required if using app-only authentication.

.PARAMETER CertificateThumbprint
The thumbprint of the certificate to use for app-only authentication. Required if using app-only authentication.

.PARAMETER AccessToken
The access token to use for authentication. Required if using app-only authentication.

.PARAMETER InteractiveLogin
Specifies whether to use interactive login. If this switch is present, interactive login will be used. Otherwise, app-only authentication will be used.

.PARAMETER OutputExcelFilePath
Specifies the path to the output Excel file. If provided, the test results will be exported to an Excel file.

.PARAMETER OutputHtmlFilePath
Specifies the path to the output HTML file. If provided, the test results will be exported to an HTML file.

.PARAMETER OutputMarkdownFilePath
Specifies the path to the output Markdown file. If provided, the test results will be exported to a Markdown file.

.PARAMETER TestedProperty
Specifies the name of the tested property. Default value is 'Has Company Name'.

.INPUTS
An array of users with DisplayName and CompanyName properties.

.OUTPUTS
If OutputExcelFilePath or OutputHtmlFilePath is not provided, the function outputs an array of custom objects with the user's display name and the result of the test.

.EXAMPLE
$users = Get-MgUser -All -Property DisplayName, CompanyName | Select-Object DisplayName, CompanyName
Test-365ACCompanyName -Users $users -OutputExcelFilePath 'C:\\TestResults.xlsx'
This example tests if the users have a company name property and exports the test results to an Excel file.
#>
Function Test-365ACCompanyName {
    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeline = $true)]
        [array]$Users = (Get-MgUser -All -Property DisplayName, CompanyName | Select-Object DisplayName, CompanyName),
        
        [Parameter(Mandatory = $false)]
        [string]$TenantID,
        
        [Parameter(Mandatory = $false)]
        [string]$ClientID,
        
        [Parameter(Mandatory = $false)]
        [string]$CertificateThumbprint,
        
        [Parameter(Mandatory = $false)]
        [string]$AccessToken,
        
        [Parameter(Mandatory = $false)]
        [switch]$InteractiveLogin,
        
        [ValidatePattern('\\.xlsx$')]
        [string]$OutputExcelFilePath,
        
        [ValidatePattern('\\.html$')]
        [string]$OutputHtmlFilePath,
        
        [ValidatePattern('\\.md$')]
        [string]$OutputMarkdownFilePath,
        
        [string]$TestedProperty = 'Has Company Name'
    )
    BEGIN {
        if ($InteractiveLogin) {
            Write-PSFMessage "Using interactive login..." -Level Host
            Connect-MgGraph -Scopes "User.Read.All", "AuditLog.read.All"  -NoWelcome
        }
        else {
            Write-PSFMessage "Using app-only authentication..." -Level Host
            Connect-MgGraph -ClientId $ClientID -TenantId $TenantID -CertificateThumbprint $CertificateThumbprint -Scopes "User.Read.All", "AuditLog.Read.All"
        }
        $results = @()
    }
    PROCESS {
        foreach ($user in $Users) {
            $hasCompanyName = [bool]($user.CompanyName)
            $result = [PSCustomObject]@{
                'User Display Name' = $user.DisplayName
                $TestedProperty     = $hasCompanyName
            }
            $results += $result
        }
    }
    END {
        $totalTests = $results.Count
        $passedTests = ($results | Where-Object { $_.$TestedProperty }).Count
        $failedTests = $totalTests - $passedTests
        if ($OutputExcelFilePath) {
            Export-365ACResultToExcel -Results $results -OutputExcelFilePath $OutputExcelFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
            Write-PSFMessage "Excel report saved to $OutputExcelFilePath" -Level Host
        }
        elseif ($OutputHtmlFilePath) {
            Export-365ACResultToHtml -Results $results -OutputHtmlFilePath $OutputHtmlFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
            Write-PSFMessage "HTML report saved to $OutputHtmlFilePath" -Level Host
        }
        elseif ($OutputMarkdownFilePath) {
            Export-365ACResultToMarkdown -Results $results -OutputMarkdownFilePath $OutputMarkdownFilePath -TotalTests $totalTests -PassedTests $passedTests -FailedTests $failedTests -TestedProperty $TestedProperty
            Write-PSFMessage "Markdown report saved to $OutputMarkdownFilePath" -Level Host
        }
        else {
            Write-PSFMessage -Level Output -Message ($results | Out-String)
        }
    }
}

And yes, it did write out the whole function again, I didn’t manipulate it at all, so after reviewing you can literally just copy it in, and not have to worry about forgetting a “(” or “{”. I know it’s not a huge lift, but you can also do “Can you also do this for #file:Test-365ACZipcode.ps1” and it will.

I’ve used this prompt syntax for other functions as well with great results. Have you used anything like this before?

You can see more uses of it at GitHub – 365AutomatedCheck

Tagged With: AI, Automation, GitHub Copilot, PowerShell, Templates

Read-Only Friday March 10, 2023

March 10, 2023 by ClaytonT Leave a Comment

It’s Friday, and I’m going to keep this one short in sweet copy. I’ve mentioned this module before, but it is so helpful if you use any of the products, that I want to make sure you don’t miss out on it! Yes, I know it’s Read-Only Friday, but this module will step up your documentation game ten fold.

AsBuiltReport on Github or you can find them on asbuiltreport.com.

What they have created is multiple modules depending on the product you need documentation on, and with one quick line of code, you get a full breakdown of the product you requesting information on. How about a 144 page document on your Active Directory? Not bad, right?

Check them out, and let me know what you think!

GitHub:
https://github.com/AsBuiltReport

Website:
https://www.asbuiltreport.com/

Tagged With: AD, Automation, Documentation, Fortigate, Fortinet, Module Monday, PowerShell, Read-Only Friday, Reporting, Veeam, VMWare, Windows Server

Module Monday January 30, 2023

January 30, 2023 by ClaytonT Leave a Comment

We are back, and hope you had a great weekend! Today’s module is one Jeff Hicks had told me about last week and I started playing with it. It’s a neat module that makes managing your tasks easy. His module is called PSWorkItem.

It allows you to create predefined categories with a description, that you can add your tasks too. You can even set the default category so that you don’t have to keep on typing the category name for each task for your primary category. The categories can highlighted in the color of your choosing if you need that feature. Another great feature is that you can input due dates and view tasks by a numnber of different filters. There is an option to put percentage complete which can be very useful if you have certain milestones for your code, and once you reach it you could have it automatically update PSWorkItem for you.

If you are looking for a simple task list that gets the job done, I highly recommend this, especially since you can easily integrate it into your coding. I know there are other ways, but you could even create a template of tasks that need to be completed for a project, then link that project so that after each task is run successfully, it automatically completes it for you.

I know Jeff has a future task of making it so you can use it with a WPF or TUI, but I’d also love to see it integrated with PowerShell Universal.

GitHub:
PSWorkItem

Tagged With: Documentation, Module Monday, PowerShell

Module Monday January 23, 2023

January 23, 2023 by ClaytonT Leave a Comment

It’s already the 4th Monday in January, can you believe it? At least that means we get an extra Module Monday next week, but lets stick to this one for right now!

Enjoy Markdown, and want to generate markdown help for your existing module, or create markdown help for modules you are currently working on? PlatyPS is the module you need.

Supported scenarios:

  • Create Markdown
    • Using existing external help files (MAML schema, XML).
    • Using reflection
    • Using reflection and existing internal external help files.
    • For a single cmdlet
    • For an entire module
  • Update existing Markdown through reflection.
  • Create a module page .md with summary. It will also allow you to create updatable help cab.
  • Retrieve markdown metadata from markdown file.
  • Create external help xml files (MAML) from platyPS Markdown.
  • Create external help file cab
  • Preview help from generated maml file.

If any of that looks to be useful, definitely check out PlatyPS!

Github:
PlatyPS

Tagged With: Documentation, Markdown, Module Monday, PowerShell

  • Page 1
  • Page 2
  • Go to Next Page »

Primary Sidebar

Clayton Tyger

Tech enthusiast dad who has lost 100lbs and now sometimes has crazy running/biking ideas. Read More…

Find Me On

  • Email
  • GitHub
  • Instagram
  • LinkedIn
  • Twitter

Recent Posts

  • Did you know: SSPR/Password Reset Edition
  • How to Delete Recurring Planner Tasks with PowerShell
  • Why does my 365 Admin Audit Log sometime say it’s disabled, but other times enabled? Am I being compromised?
  • EntraFIDOFinder Update
  • New version of EntraFIDOFinder is out now

Categories

  • 365
  • Active Directory
  • AI
  • AzureAD
  • BlueSky
  • Cim
  • Dashboards
  • Documentation
  • Entra
  • Get-WMI
  • Learning
  • Module Monday
  • Nutanix
  • One Liner Wednesday
  • Passwords
  • PDF
  • Planner
  • PowerShell
  • Read-Only Friday
  • Reporting
  • Security
  • Windows
  • WSUS

© 2025 Clatent