Showing preview only (532K chars total). Download the full file or copy to clipboard to get everything.
Repository: EvotecIT/PasswordSolution
Branch: master
Commit: 2d674fe39473
Files: 64
Total size: 506.8 KB
Directory structure:
gitextract_pdir1fnf/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── Build/
│ └── Manage-Module.ps1
├── CHANGELOG.MD
├── Docs/
│ ├── Find-Password.md
│ ├── Find-PasswordNotification.md
│ ├── Find-PasswordQuality.md
│ ├── New-PasswordConfigurationEmail.md
│ ├── New-PasswordConfigurationOption.md
│ ├── New-PasswordConfigurationReport.md
│ ├── New-PasswordConfigurationRule.md
│ ├── New-PasswordConfigurationRuleReminder.md
│ ├── New-PasswordConfigurationTemplate.md
│ ├── New-PasswordConfigurationType.md
│ ├── Readme.md
│ ├── Show-PasswordQuality.md
│ └── Start-PasswordSolution.md
├── Examples/
│ ├── Example-EncryptPassword.ps1
│ ├── Example-FindUsers.ps1
│ ├── Example-FindUsersAdvanced.ps1
│ ├── Example-FindUsersEntra.ps1
│ ├── Example-FindUsersPasswordQualityConsole.ps1
│ ├── Example-FindUsersPasswordQualityConsoleWithReplacements.ps1
│ ├── Example-FindUsersPasswordQualityReport.ps1
│ ├── Example-FindUsersPasswordQualityReportWithReplacements.ps1
│ ├── Example-PasswordDashboard.ps1
│ ├── Example-PasswordSolution-Entra.ps1
│ ├── Example-PasswordSolution-LegacyConfiguration01.ps1
│ ├── Example-PasswordSolution-ModernConfiguration01.ps1
│ ├── Example-ReRegisterTaskAsGMSA.ps1
│ ├── Example-SearchNotification.ps1
│ └── WeakPasswordGenerator.ps1
├── PasswordSolution.psd1
├── PasswordSolution.psm1
├── Private/
│ ├── Add-ManagerInformation.ps1
│ ├── Add-ParametersToString.ps1
│ ├── Export-SearchInformation.ps1
│ ├── Fromat-ReminderDays.ps1
│ ├── Import-SearchInformation.ps1
│ ├── Invoke-PasswordRuleProcessing.ps1
│ ├── New-HTMLReport.ps1
│ ├── Send-PasswordAdminNotifications.ps1
│ ├── Send-PasswordEmail.ps1
│ ├── Send-PasswordManagerNotifications.ps1
│ ├── Send-PasswordSecurityNotifications.ps1
│ ├── Send-PasswordUserNotifications.ps1
│ └── Set-PasswordConfiguration.ps1
├── Public/
│ ├── Find-Password.ps1
│ ├── Find-PasswordEntra.ps1
│ ├── Find-PasswordNotification.ps1
│ ├── Find-PasswordQuality.ps1
│ ├── New-PasswordConfigurationEmail.ps1
│ ├── New-PasswordConfigurationEntra.ps1
│ ├── New-PasswordConfigurationExternalUsers.ps1
│ ├── New-PasswordConfigurationOption.ps1
│ ├── New-PasswordConfigurationReplacement.ps1
│ ├── New-PasswordConfigurationReport.ps1
│ ├── New-PasswordConfigurationRule.ps1
│ ├── New-PasswordConfigurationRuleReminder.ps1
│ ├── New-PasswordConfigurationTemplate.ps1
│ ├── New-PasswordConfigurationType.ps1
│ ├── Show-PasswordQuality.ps1
│ └── Start-PasswordSolution.ps1
└── README.MD
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
github: PrzemyslawKlys
custom: https://paypal.me/PrzemyslawKlys
================================================
FILE: .gitignore
================================================
Ignore/*
.vs/*
.vscode/*
*.html
*.log
*.xml
Artefacts/*
================================================
FILE: Build/Manage-Module.ps1
================================================
Clear-Host
Import-Module "PSPublishModule" -Force
Invoke-ModuleBuild -ModuleName 'PasswordSolution' {
# Usual defaults as per standard module
$Manifest = [ordered] @{
# Version number of this module.
ModuleVersion = '2.1.X'
# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')
PowerShellVersion = '5.1'
# ID used to uniquely identify this module
GUID = 'c58ff818-1de6-4500-961c-a243c2043255'
# Author of this module
Author = 'Przemyslaw Klys'
# Company or vendor of this module
CompanyName = 'Evotec'
# Copyright statement for this module
Copyright = "(c) 2011 - $((Get-Date).Year) Przemyslaw Klys @ Evotec. All rights reserved."
# Description of the functionality provided by this module
Description = "This module allows the creation of password expiry emails for users, managers, administrators, and security according to defined templates. It's able to work with different rules allowing to fully customize who gets the email and when."
# Minimum version of the Windows PowerShell engine required by this module
Tags = 'password', 'passwordexpiry', 'activedirectory', 'windows'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/EvotecIT/PasswordSolution'
# A URL to an icon representing this module.
IconUri = 'https://evotec.xyz/wp-content/uploads/2022/08/PasswordSolution.png'
}
New-ConfigurationManifest @Manifest
New-ConfigurationModule -Type RequiredModule -Name 'PSSharedGoods', 'PSWriteHTML', 'PSWriteColor' -Guid Auto -Version Latest
New-ConfigurationModule -Type RequiredModule -Name 'Mailozaurr' -Guid Auto -Version 1.0.0
New-ConfigurationModule -Type ExternalModule -Name @(
#"Microsoft.PowerShell.Management"
#"Microsoft.PowerShell.Utility"
"ActiveDirectory"
)
New-ConfigurationModule -Type ApprovedModule -Name 'PSSharedGoods', 'PSWriteColor', 'Connectimo', 'PSUnifi', 'PSWebToolbox', 'PSMyPassword'
New-ConfigurationModuleSkip -IgnoreModuleName @(
# Default modules
'NetTCPIP'
'Microsoft.WSMan.Management'
# Password Quality
'DSInternals'
# Graph Cmdlets
'Microsoft.Graph.Users'
'Microsoft.Graph.Identity.DirectoryManagement'
) -IgnoreFunctionName @(
'Select-Unique', 'Compare-TwoArrays' # those functions are internal within private function
# Password Quality
'Get-ADReplAccount'
'Test-PasswordQuality'
# Graph Cmdlets
'Get-MgDomain'
'Get-MgUser'
)
$ConfigurationFormat = [ordered] @{
RemoveComments = $true
RemoveEmptyLines = $true
PlaceOpenBraceEnable = $true
PlaceOpenBraceOnSameLine = $true
PlaceOpenBraceNewLineAfter = $true
PlaceOpenBraceIgnoreOneLineBlock = $false
PlaceCloseBraceEnable = $true
PlaceCloseBraceNewLineAfter = $false
PlaceCloseBraceIgnoreOneLineBlock = $true
PlaceCloseBraceNoEmptyLineBefore = $false
UseConsistentIndentationEnable = $true
UseConsistentIndentationKind = 'space'
UseConsistentIndentationPipelineIndentation = 'IncreaseIndentationAfterEveryPipeline'
UseConsistentIndentationIndentationSize = 4
UseConsistentWhitespaceEnable = $true
UseConsistentWhitespaceCheckInnerBrace = $true
UseConsistentWhitespaceCheckOpenBrace = $true
UseConsistentWhitespaceCheckOpenParen = $true
UseConsistentWhitespaceCheckOperator = $true
UseConsistentWhitespaceCheckPipe = $true
UseConsistentWhitespaceCheckSeparator = $true
AlignAssignmentStatementEnable = $true
AlignAssignmentStatementCheckHashtable = $true
UseCorrectCasingEnable = $true
}
# format PSD1 and PSM1 files when merging into a single file
# enable formatting is not required as Configuration is provided
New-ConfigurationFormat -ApplyTo 'OnMergePSM1', 'OnMergePSD1' -Sort None @ConfigurationFormat
# format PSD1 and PSM1 files within the module
# enable formatting is required to make sure that formatting is applied (with default settings)
New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'DefaultPSM1' -EnableFormatting -Sort None
# when creating PSD1 use special style without comments and with only required parameters
New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'OnMergePSD1' -PSD1Style 'Minimal'
# configuration for documentation, at the same time it enables documentation processing
New-ConfigurationDocumentation -Enable:$false -StartClean -UpdateWhenNew -PathReadme 'Docs\Readme.md' -Path 'Docs'
New-ConfigurationImportModule -ImportSelf
New-ConfigurationBuild -Enable:$true -SignModule -MergeModuleOnBuild -MergeFunctionsFromApprovedModules -CertificateThumbprint '483292C9E317AA13B07BB7A96AE9D1A5ED9E7703'
#New-ConfigurationTest -TestsPath "$PSScriptRoot\..\Tests" -Enable
New-ConfigurationArtefact -Type Unpacked -Enable -Path "$PSScriptRoot\..\Artefacts\Unpacked" -AddRequiredModules
New-ConfigurationArtefact -Type Packed -Enable -Path "$PSScriptRoot\..\Artefacts\Packed" -ArtefactName '<ModuleName>.v<ModuleVersion>.zip'
# options for publishing to github/psgallery
#New-ConfigurationPublish -Type PowerShellGallery -FilePath 'C:\Support\Important\PowerShellGalleryAPI.txt' -Enabled:$true
#New-ConfigurationPublish -Type GitHub -FilePath 'C:\Support\Important\GitHubAPI.txt' -UserName 'EvotecIT' -Enabled:$true
} -ExitCode
================================================
FILE: CHANGELOG.MD
================================================
# PasswordSolution Release History
## 2.0.3
- Fix formatting in HTML output
- Fix deletion of log files/reports to specific extensions only [#24](https://github.com/EvotecIT/PasswordSolution/issues/24)
## 2.0.2 - 2024.10.01
- Add `SearchBase` when managers are not required, or the scope for both users and managers is very limited (use FilterOrganizationalUnit instead)
## 2.0.1 - 2024.09.30
- Fixes `AdminSection` not working properly for modern configuration
- Improve error reporting when sending emails
## 2.0.0 - 2024.09.08 - **EXPERIMENTAL**
- Added basic support for Microsoft Entra ID (Azure AD)
- Improved reporting allowing to exclude properties from HTML reports to make them smaller
- Hide **'Manager', 'ManagerDN', 'MemberOf'** by default in HTML reports (zero out ExcludeProperties to get rid of this behavior)
- Made `ScrollX` default to `true` in HTML reports to make them more readable
## 1.3.2 - 2024.08.23
- Improvement on logging
- Small improvement to message
## 1.3.1 - 2024.08.23
- Fixes `FilterOrganizationalUnit` not working properly
- Add more logs
## 1.3.0 - 2024.08.23
- Added `NotifyOnUserMatchingRuleForManager`, `NotifyOnUserMatchingRuleForManagerButNotCompliant` to `New-PasswordConfigurationOption` to allow for more granular control over logging
- Fixes sending emails to managers based on weekdays when using modern setup configuration
- Added additional check logic to prevent wrong rules configuration
## 1.2.9 - 2024.08.22
- Fixes logging functionality when using modern settings
## 1.2.8 - 2024.08.22
- Added `FilterOrganizationalUnit` to `New-PasswordConfigurationOption` to allow for filtering users based on OrganizationalUnit
This speeds up the process of scanning users, and allows for more granular control over which users are scanned without having to go thru all users in the domain
The module still gets all the users but only processes the ones that match the filter
- Improved console colors a bit, to prevent some colors from being invisible
```powershell
$Options = @{
# Logging to file and to screen
ShowTime = $true
LogFile = "$PSScriptRoot\Logs\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).log"
TimeFormat = "yyyy-MM-dd HH:mm:ss"
LogMaximum = 365
NotifyOnSkipUserManagerOnly = $false
NotifyOnSecuritySend = $true
NotifyOnManagerSend = $true
NotifyOnUserSend = $true
NotifyOnUserMatchingRule = $false
NotifyOnUserDaysToExpireNull = $false
SearchPath = "$PSScriptRoot\Search\SearchLog_$((Get-Date).ToString('yyyy-MM')).xml"
EmailDateFormat = "yyyy-MM-dd"
EmailDateFormatUTCConversion = $true
FilterOrganizationalUnit = @(
"*OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
"*OU=Administration,DC=ad,DC=evotec,DC=xyz"
)
}
New-PasswordConfigurationOption @Options
```
## 1.2.7 - 2024.08.21
- Adds sending email without credentials (using SMTP server)
- Fixes `SkipCertificateValidation` typo in `New-PasswordConfigurationEmail`
- Small cleanup
## 1.2.6 - 2024.08.12
- Fix wrong publish of cmdlets
## 1.2.5 - 2024.07.16
- Remove duplicate records from external managers
## 1.2.4 - 2024.07.15
- Fixes email address being wrong when using external system and using overwrite property
## 1.2.3 - 2024.06.23
- Small report improvements
## 1.2.2 - 2024.06.23
- Add reporting for replacements of emails from external sources
## 1.2.1 - 2024.06.23
- Allow using DSL and normal configuration at the same time
## 1.2.0 - 2024.06.23
- This version adds ability to allow overwritting email address from external system, or even CSV records based on prepared data
- Added `New-PasswordConfigurationExternalUsers` to allow for overwritting emails with external data in form of array of objects
## 1.1.1 - 2024.01.16
- Small improvement to error message being provided when sending email fails with summary of emails
## 1.1.0 - 2023.11.12
- Add support for weak password hashes (NTLM) in Password Quality Check
- Add new parameters for `Find-PasswordQuality`
- Add new parameters for `Show-PasswordQuality`
## 1.0.5 - 2023.10.18
- I can't type apparently so I fixed typo in code
## 1.0.3 - 2023.06.12
- Resolves issue with scanning **Active Directory** without exchange attributes
## 1.0.2 - 2023.06.06
- Improves `New-PasswordConfigurationRuleReminder` by allowing: `New-PasswordConfigurationRuleReminder -Type 'Manager' -ExpirationDays @(-200..-1), 0, 1, 2, 3, 7, 15, 30, 60 -ComparisonType eq` configuration
## 1.0.1 - 2023.06.01
- Fixes AdminSection not working properly
## 1.0.0 - 2023.05.25
- Improves exclusions https://github.com/EvotecIT/PasswordSolution/issues/7
- Simplifies configuration https://github.com/EvotecIT/PasswordSolution/issues/8
- Improves configuration https://github.com/EvotecIT/PasswordSolution/issues/3
- Improves configuration https://github.com/EvotecIT/PasswordSolution/issues/6
- Improve HTML report to be better in naming things
- Allow for overwriting manager field with different properties based on SamAccountName/DN
- New configuration option for Report (NestedRules), making separate tab for all rules in HTML
- Small documentation updates
- Adds defaults for templates meaning it's possible to skip their definitions although not very useful if you want personalized thing for your company users
This actually means:
- We now support DSL language for configuration (see examples)
- We now support much easier way of building configuration
- We now support overwrite email property per rule (global still works)
- We now support overwrite manager property per rule (global still works)
## 0.0.37 - 2023.04.25
- Improve `Maps` in Password Quality
- Improve colors, add column to a report
## 0.0.36 - 2023.04.24
- Added `Maps` to Password Quality
- Improved reporting in Password Quality with countries for Weak Passwords and Duplicate Groups
- Added Logs to Password Quality
- Minor improvements to reporting
- Make report much smaller
## 0.0.35 - 2023.04.19
- Small fix to report
## 0.0.34 - 2023.04.19
- Fixes reporting of quality passwords in overview, charts
- Removed tables for Duplicate Groups in favor of single table (1000 tabs don't seem to work in HTML 🤯)
## 0.0.33 - 2023.04.18
- General improvements
- Added separate duplicate groups tables to report for easier visibility
- Prefer writable DCs when quering AD
## 0.0.32 - 2023.01.18
- Removed DSInternals from required modules (made it optional / disables Password Quality Check). This is to not trigger any security alerts in your environment if you just want to use the module for password expiration and not password quality checks.
## 0.0.31 - 2023.01.17
- Small updates to logging
## 0.0.30 - 2023.01.17
- Add ability to check password quality (requires higher permissions) and based on DSInternals
## 0.0.29 - 2022.10.11
- Fixes to report **ShowSkippedUsers** to skip Contacts
## 0.0.28
- Fixes to report **All Users** to skip Contacts
- Fixes to report conditional formatting which would format unnessecary fields
## 0.0.26
- Remove Body from **EmailConfiguration** in HTML Report
- Fixes an issue with table in reports having borders (from the EmailBody)
## 0.0.25
- Fix ManagerStatus when Overwriteproperty is in use
- Add HTML report to Email to Admins
```powershell
HTMLReports = @(
# Accepts a list of reports to generate. Can be multiple reprorts having different sections, or just one having it all
[ordered] @{
Enable = $true
ShowHTML = $true
Title = "Password Solution Summary"
Online = $true
DisableWarnings = $true
ShowConfiguration = $true
ShowAllUsers = $true
ShowRules = $true
ShowUsersSent = $true
ShowManagersSent = $true
ShowEscalationSent = $true
ShowSkippedUsers = $true
ShowSkippedLocations = $true
ShowSearchUsers = $true
ShowSearchManagers = $true
ShowSearchEscalations = $true
FilePath = "$PSScriptRoot\Reporting\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html"
AttachToEmail = $true # new option
}
)
```
## 0.0.24
- Bump dependencies of PSWriteHTML, Mailozaurr to newest versions
- Add support for managers of users being a Contact (with an email field)
## 0.0.23
- Small cleanup
- Docs update
## 0.0.22
- Fixes dashboard not showing some objects
- Added properties describing which rule was used to find user
- Added some additional logging
================================================
FILE: Docs/Find-Password.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# Find-Password
## SYNOPSIS
Scan Active Directory forest for all users and their password expiration date
## SYNTAX
```
Find-Password [[-Forest] <String>] [[-ExcludeDomains] <String[]>] [[-IncludeDomains] <String[]>]
[[-ExtendedForestInformation] <IDictionary>] [[-OverwriteEmailProperty] <String>]
[[-ReturnObjectsType] <String[]>] [[-OverwriteManagerProperty] <String>] [<CommonParameters>]
```
## DESCRIPTION
Scan Active Directory forest for all users and their password expiration date
## EXAMPLES
### EXAMPLE 1
```
Find-Password | ft
```
## PARAMETERS
### -Forest
Target different Forest, by default current forest is used
```yaml
Type: String
Parameter Sets: (All)
Aliases: ForestName
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeDomains
Exclude domain from search, by default whole forest is scanned
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeDomains
Include only specific domains, by default whole forest is scanned
```yaml
Type: String[]
Parameter Sets: (All)
Aliases: Domain, Domains
Required: False
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExtendedForestInformation
Ability to provide Forest Information from another command to speed up processing
```yaml
Type: IDictionary
Parameter Sets: (All)
Aliases:
Required: False
Position: 4
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteEmailProperty
Overwrite EmailAddress property with different property name
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 5
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ReturnObjectsType
{{ Fill ReturnObjectsType Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 7
Default value: @('Users', 'Contacts')
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteManagerProperty
Overwrite Manager property with different property name.
Can use DistinguishedName or SamAccountName
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 10
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
## OUTPUTS
## NOTES
General notes
## RELATED LINKS
================================================
FILE: Docs/Find-PasswordNotification.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# Find-PasswordNotification
## SYNOPSIS
Searches thru XML logs created by Password Solution
## SYNTAX
```
Find-PasswordNotification [-SearchPath] <String> [-Manager] [<CommonParameters>]
```
## DESCRIPTION
Searches thru XML logs created by Password Solution
## EXAMPLES
### EXAMPLE 1
```
Find-PasswordNotification -SearchPath $PSScriptRoot\Search\SearchLog.xml | Format-Table
```
### EXAMPLE 2
```
Find-PasswordNotification -SearchPath "$PSScriptRoot\Search\SearchLog_2021-06.xml" -Manager | Format-Table
```
## PARAMETERS
### -SearchPath
Path to file where the XML log is located
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: True
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Manager
Search thru manager escalations
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
## OUTPUTS
## NOTES
General notes
## RELATED LINKS
================================================
FILE: Docs/Find-PasswordQuality.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# Find-PasswordQuality
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
Find-PasswordQuality [[-WeakPasswords] <String[]>] [-IncludeStatistics] [[-Forest] <String>]
[[-ExcludeDomains] <String[]>] [[-IncludeDomains] <String[]>] [[-ExtendedForestInformation] <IDictionary>]
[<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -WeakPasswords
{{ Fill WeakPasswords Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeStatistics
{{ Fill IncludeStatistics Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Forest
Target different Forest, by default current forest is used
```yaml
Type: String
Parameter Sets: (All)
Aliases: ForestName
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeDomains
Exclude domain from search, by default whole forest is scanned
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeDomains
Include only specific domains, by default whole forest is scanned
```yaml
Type: String[]
Parameter Sets: (All)
Aliases: Domain, Domains
Required: False
Position: 4
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExtendedForestInformation
Ability to provide Forest Information from another command to speed up processing
```yaml
Type: IDictionary
Parameter Sets: (All)
Aliases:
Required: False
Position: 5
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationEmail.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationEmail
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
### Compatibility
```
New-PasswordConfigurationEmail [-Server <String>] [-Port <Int32>] -From <Object> [-ReplyTo <String>]
[-Priority <String>] [-DeliveryNotificationOption <String[]>]
[-DeliveryStatusNotificationType <DeliveryStatusNotificationType>] [-Credential <PSCredential>]
[-SecureSocketOptions <SecureSocketOptions>] [-UseSsl] [-SkipCertificateRevocation]
[-SkipCertificateValidatation] [-Timeout <Int32>] [-LocalDomain <String>] [-WhatIf] [-Confirm]
[<CommonParameters>]
```
### oAuth
```
New-PasswordConfigurationEmail [-Server <String>] [-Port <Int32>] -From <Object> [-ReplyTo <String>]
[-Priority <String>] [-DeliveryNotificationOption <String[]>]
[-DeliveryStatusNotificationType <DeliveryStatusNotificationType>] [-Credential <PSCredential>]
[-SecureSocketOptions <SecureSocketOptions>] [-UseSsl] [-SkipCertificateRevocation]
[-SkipCertificateValidatation] [-Timeout <Int32>] [-oAuth2] [-LocalDomain <String>] [-WhatIf] [-Confirm]
[<CommonParameters>]
```
### SecureString
```
New-PasswordConfigurationEmail [-Server <String>] [-Port <Int32>] -From <Object> [-ReplyTo <String>]
[-Priority <String>] [-DeliveryNotificationOption <String[]>]
[-DeliveryStatusNotificationType <DeliveryStatusNotificationType>] [-Username <String>] [-Password <String>]
[-SecureSocketOptions <SecureSocketOptions>] [-UseSsl] [-SkipCertificateRevocation]
[-SkipCertificateValidatation] [-Timeout <Int32>] [-AsSecureString] [-LocalDomain <String>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```
### SendGrid
```
New-PasswordConfigurationEmail -From <Object> [-ReplyTo <String>] [-Priority <String>]
-Credential <PSCredential> [-SendGrid] [-SeparateTo] [-WhatIf] [-Confirm] [<CommonParameters>]
```
### MgGraphRequest
```
New-PasswordConfigurationEmail -From <Object> [-ReplyTo <String>] [-Priority <String>] [-RequestReadReceipt]
[-RequestDeliveryReceipt] [-Graph] [-MgGraphRequest] [-DoNotSaveToSentItems] [-WhatIf] [-Confirm]
[<CommonParameters>]
```
### Graph
```
New-PasswordConfigurationEmail -From <Object> [-ReplyTo <String>] [-Priority <String>]
-Credential <PSCredential> [-RequestReadReceipt] [-RequestDeliveryReceipt] [-Graph] [-DoNotSaveToSentItems]
[-WhatIf] [-Confirm] [<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -AsSecureString
{{ Fill AsSecureString Description }}
```yaml
Type: SwitchParameter
Parameter Sets: SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Confirm
Prompts you for confirmation before running the cmdlet.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases: cf
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Credential
{{ Fill Credential Description }}
```yaml
Type: PSCredential
Parameter Sets: Compatibility, oAuth
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
```yaml
Type: PSCredential
Parameter Sets: SendGrid, Graph
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DeliveryNotificationOption
{{ Fill DeliveryNotificationOption Description }}
```yaml
Type: String[]
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Accepted values: None, OnSuccess, OnFailure, Delay, Never
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DeliveryStatusNotificationType
{{ Fill DeliveryStatusNotificationType Description }}
```yaml
Type: DeliveryStatusNotificationType
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Accepted values: Unspecified, Full, HeadersOnly
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DoNotSaveToSentItems
{{ Fill DoNotSaveToSentItems Description }}
```yaml
Type: SwitchParameter
Parameter Sets: MgGraphRequest, Graph
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -From
{{ Fill From Description }}
```yaml
Type: Object
Parameter Sets: (All)
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Graph
{{ Fill Graph Description }}
```yaml
Type: SwitchParameter
Parameter Sets: MgGraphRequest, Graph
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -LocalDomain
{{ Fill LocalDomain Description }}
```yaml
Type: String
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -MgGraphRequest
{{ Fill MgGraphRequest Description }}
```yaml
Type: SwitchParameter
Parameter Sets: MgGraphRequest
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Password
{{ Fill Password Description }}
```yaml
Type: String
Parameter Sets: SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Port
{{ Fill Port Description }}
```yaml
Type: Int32
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Priority
{{ Fill Priority Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases: Importance
Accepted values: Low, Normal, High
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ReplyTo
{{ Fill ReplyTo Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -RequestDeliveryReceipt
{{ Fill RequestDeliveryReceipt Description }}
```yaml
Type: SwitchParameter
Parameter Sets: MgGraphRequest, Graph
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -RequestReadReceipt
{{ Fill RequestReadReceipt Description }}
```yaml
Type: SwitchParameter
Parameter Sets: MgGraphRequest, Graph
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SecureSocketOptions
{{ Fill SecureSocketOptions Description }}
```yaml
Type: SecureSocketOptions
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Accepted values: None, Auto, SslOnConnect, StartTls, StartTlsWhenAvailable
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SendGrid
{{ Fill SendGrid Description }}
```yaml
Type: SwitchParameter
Parameter Sets: SendGrid
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SeparateTo
{{ Fill SeparateTo Description }}
```yaml
Type: SwitchParameter
Parameter Sets: SendGrid
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Server
{{ Fill Server Description }}
```yaml
Type: String
Parameter Sets: Compatibility, oAuth, SecureString
Aliases: SmtpServer
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SkipCertificateRevocation
{{ Fill SkipCertificateRevocation Description }}
```yaml
Type: SwitchParameter
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SkipCertificateValidatation
{{ Fill SkipCertificateValidatation Description }}
```yaml
Type: SwitchParameter
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Timeout
{{ Fill Timeout Description }}
```yaml
Type: Int32
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -UseSsl
{{ Fill UseSsl Description }}
```yaml
Type: SwitchParameter
Parameter Sets: Compatibility, oAuth, SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Username
{{ Fill Username Description }}
```yaml
Type: String
Parameter Sets: SecureString
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -WhatIf
Shows what would happen if the cmdlet runs. The cmdlet is not run.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases: wi
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -oAuth2
{{ Fill oAuth2 Description }}
```yaml
Type: SwitchParameter
Parameter Sets: oAuth
Aliases: oAuth
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationOption.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationOption
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
New-PasswordConfigurationOption [-ShowTime] [[-LogFile] <String>] [[-TimeFormat] <String>]
[[-LogMaximum] <Int32>] [-NotifyOnSkipUserManagerOnly] [-NotifyOnSecuritySend] [-NotifyOnManagerSend]
[-NotifyOnUserSend] [-NotifyOnUserMatchingRule] [-NotifyOnUserDaysToExpireNull] [[-SearchPath] <String>]
[[-EmailDateFormat] <String>] [-EmailDateFormatUTCConversion] [[-OverwriteEmailProperty] <String>]
[[-OverwriteManagerProperty] <String>] [<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -EmailDateFormat
{{ Fill EmailDateFormat Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 4
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -EmailDateFormatUTCConversion
{{ Fill EmailDateFormatUTCConversion Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -LogFile
{{ Fill LogFile Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 0
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -LogMaximum
{{ Fill LogMaximum Description }}
```yaml
Type: Int32
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NotifyOnManagerSend
{{ Fill NotifyOnManagerSend Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NotifyOnSecuritySend
{{ Fill NotifyOnSecuritySend Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NotifyOnSkipUserManagerOnly
{{ Fill NotifyOnSkipUserManagerOnly Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NotifyOnUserDaysToExpireNull
{{ Fill NotifyOnUserDaysToExpireNull Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NotifyOnUserMatchingRule
{{ Fill NotifyOnUserMatchingRule Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NotifyOnUserSend
{{ Fill NotifyOnUserSend Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteEmailProperty
{{ Fill OverwriteEmailProperty Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 5
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteManagerProperty
{{ Fill OverwriteManagerProperty Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 6
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SearchPath
{{ Fill SearchPath Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowTime
{{ Fill ShowTime Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TimeFormat
{{ Fill TimeFormat Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationReport.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationReport
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
New-PasswordConfigurationReport [-Enable] [-ShowHTML] [[-Title] <String>] [-Online] [-DisableWarnings]
[-ShowConfiguration] [-ShowAllUsers] [-ShowRules] [-ShowUsersSent] [-ShowManagersSent] [-ShowEscalationSent]
[-ShowSkippedUsers] [-ShowSkippedLocations] [-ShowSearchUsers] [-ShowSearchManagers] [-ShowSearchEscalations]
[[-FilePath] <String>] [-AttachToEmail] [-NestedRules] [<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -Enable
{{ Fill Enable Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowHTML
{{ Fill ShowHTML Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Title
{{ Fill Title Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Online
{{ Fill Online Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DisableWarnings
{{ Fill DisableWarnings Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowConfiguration
{{ Fill ShowConfiguration Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowAllUsers
{{ Fill ShowAllUsers Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowRules
{{ Fill ShowRules Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowUsersSent
{{ Fill ShowUsersSent Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowManagersSent
{{ Fill ShowManagersSent Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowEscalationSent
{{ Fill ShowEscalationSent Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowSkippedUsers
{{ Fill ShowSkippedUsers Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowSkippedLocations
{{ Fill ShowSkippedLocations Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowSearchUsers
{{ Fill ShowSearchUsers Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowSearchManagers
{{ Fill ShowSearchManagers Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ShowSearchEscalations
{{ Fill ShowSearchEscalations Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -FilePath
{{ Fill FilePath Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -AttachToEmail
{{ Fill AttachToEmail Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -NestedRules
Specifies whether to display nested password rules.
Each rule has it's own tab with output.
Having many rules and all other settings enabled can result in a very long list of tabs that's hard to navigate.
This setting forces separate tab for all rules.
The default value is $false.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationRule.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationRule
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
New-PasswordConfigurationRule [[-ReminderConfiguration] <ScriptBlock>] [-Name] <String> [-Enable]
[-IncludeExpiring] [-IncludePasswordNeverExpires] [[-PasswordNeverExpiresDays] <Int32>]
[[-IncludeNameProperties] <String[]>] [[-IncludeName] <String[]>] [[-ExcludeNameProperties] <String[]>]
[[-ExcludeName] <String[]>] [[-IncludeOU] <String[]>] [[-ExcludeOU] <String[]>] [[-IncludeGroup] <String[]>]
[[-ExcludeGroup] <String[]>] [-ReminderDays] <Array> [-ManagerReminder] [-ManagerNotCompliant]
[[-ManagerNotCompliantDisplayName] <String>] [[-ManagerNotCompliantEmailAddress] <String>]
[-ManagerNotCompliantDisabled] [-ManagerNotCompliantMissing] [-ManagerNotCompliantMissingEmail]
[[-ManagerNotCompliantLastLogonDays] <Int32>] [-SecurityEscalation]
[[-SecurityEscalationDisplayName] <String>] [[-SecurityEscalationEmailAddress] <String>]
[[-OverwriteEmailProperty] <String>] [[-OverwriteManagerProperty] <String>] [-ProcessManagersOnly]
[<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -ReminderConfiguration
{{ Fill ReminderConfiguration Description }}
```yaml
Type: ScriptBlock
Parameter Sets: (All)
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Name
{{ Fill Name Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: True
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Enable
{{ Fill Enable Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeExpiring
{{ Fill IncludeExpiring Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludePasswordNeverExpires
{{ Fill IncludePasswordNeverExpires Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -PasswordNeverExpiresDays
{{ Fill PasswordNeverExpiresDays Description }}
```yaml
Type: Int32
Parameter Sets: (All)
Aliases:
Required: False
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeNameProperties
{{ Fill IncludeNameProperties Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 4
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeName
{{ Fill IncludeName Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 5
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeNameProperties
Exclude user from rule if any of the properties match the value as defined in ExcludeName
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 6
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeName
Exclude user from rule if any of the properties match the value of Name in the properties defined in ExcludeNameProperties
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 7
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeOU
{{ Fill IncludeOU Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 8
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeOU
{{ Fill ExcludeOU Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 9
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeGroup
Parameter description
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 10
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeGroup
Parameter description
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 11
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ReminderDays
Parameter description
```yaml
Type: Array
Parameter Sets: (All)
Aliases: ExpirationDays, Days
Required: True
Position: 12
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerReminder
{{ Fill ManagerReminder Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliant
{{ Fill ManagerNotCompliant Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliantDisplayName
{{ Fill ManagerNotCompliantDisplayName Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 13
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliantEmailAddress
{{ Fill ManagerNotCompliantEmailAddress Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 14
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliantDisabled
{{ Fill ManagerNotCompliantDisabled Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliantMissing
{{ Fill ManagerNotCompliantMissing Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliantMissingEmail
{{ Fill ManagerNotCompliantMissingEmail Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerNotCompliantLastLogonDays
{{ Fill ManagerNotCompliantLastLogonDays Description }}
```yaml
Type: Int32
Parameter Sets: (All)
Aliases:
Required: False
Position: 15
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SecurityEscalation
{{ Fill SecurityEscalation Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SecurityEscalationDisplayName
{{ Fill SecurityEscalationDisplayName Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 16
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SecurityEscalationEmailAddress
{{ Fill SecurityEscalationEmailAddress Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 17
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteEmailProperty
Parameter description
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 18
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteManagerProperty
Parameter description
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 19
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ProcessManagersOnly
This parameters is used to process users, but only managers will be notified.
Sending emails to users within the rule will be skipped completly.
This is useful if users would have email addresses, that would normally trigger an email to them.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationRuleReminder.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationRuleReminder
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
### Daily (Default)
```
New-PasswordConfigurationRuleReminder -Type <String> -ExpirationDays <Array> [-ComparisonType <String>]
[<CommonParameters>]
```
### DayOfMonth
```
New-PasswordConfigurationRuleReminder -Type <String> -ExpirationDays <Array> -DayOfMonth <Array>
[-ComparisonType <String>] [<CommonParameters>]
```
### DayOfWeek
```
New-PasswordConfigurationRuleReminder -Type <String> -ExpirationDays <Array> -DayOfWeek <Array>
[-ComparisonType <String>] [<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -ComparisonType
{{ Fill ComparisonType Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Accepted values: lt, gt, eq, in
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DayOfMonth
{{ Fill DayOfMonth Description }}
```yaml
Type: Array
Parameter Sets: DayOfMonth
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DayOfWeek
{{ Fill DayOfWeek Description }}
```yaml
Type: Array
Parameter Sets: DayOfWeek
Aliases:
Accepted values: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExpirationDays
{{ Fill ExpirationDays Description }}
```yaml
Type: Array
Parameter Sets: (All)
Aliases: ConditionDays, Days
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Type
{{ Fill Type Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Accepted values: Manager, ManagerNotCompliant, Security
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationTemplate.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationTemplate
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
New-PasswordConfigurationTemplate [-Template] <ScriptBlock> [-Subject] <String> [-Type] <Object>
[<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -Subject
{{ Fill Subject Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: True
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Template
{{ Fill Template Description }}
```yaml
Type: ScriptBlock
Parameter Sets: (All)
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Type
{{ Fill Type Description }}
```yaml
Type: Object
Parameter Sets: (All)
Aliases:
Accepted values: PreExpiry, PostExpiry, Manager, ManagerNotCompliant, Security, Admin
Required: True
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/New-PasswordConfigurationType.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# New-PasswordConfigurationType
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
New-PasswordConfigurationType [-Type] <String> [-Enable] [[-SendCountMaximum] <Int32>]
[[-DefaultEmail] <String>] [-AttachCSV] [<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -AttachCSV
{{ Fill AttachCSV Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DefaultEmail
{{ Fill DefaultEmail Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Enable
{{ Fill Enable Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SendCountMaximum
{{ Fill SendCountMaximum Description }}
```yaml
Type: Int32
Parameter Sets: (All)
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Type
{{ Fill Type Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Accepted values: User, Manager, Security, Admin
Required: True
Position: 0
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/Readme.md
================================================
---
Module Name: PasswordSolution
Module Guid: c58ff818-1de6-4500-961c-a243c2043255
Download Help Link: {{ Update Download Link }}
Help Version: {{ Please enter version of help manually (X.X.X.X) format }}
Locale: en-US
---
# PasswordSolution Module
## Description
PasswordSolution is a PowerShell module that provides Password Expiry notifications to users, managers, security and administrators. It's very configurable and was designed for enterprise use.
## PasswordSolution Cmdlets
### [Find-Password](Find-Password.md)
Scan Active Directory forest for all users and their password expiration date
### [Find-PasswordNotification](Find-PasswordNotification.md)
Searches thru XML logs created by Password Solution
### [Find-PasswordQuality](Find-PasswordQuality.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationEmail](New-PasswordConfigurationEmail.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationOption](New-PasswordConfigurationOption.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationReport](New-PasswordConfigurationReport.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationRule](New-PasswordConfigurationRule.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationRuleReminder](New-PasswordConfigurationRuleReminder.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationTemplate](New-PasswordConfigurationTemplate.md)
{{ Fill in the Synopsis }}
### [New-PasswordConfigurationType](New-PasswordConfigurationType.md)
{{ Fill in the Synopsis }}
### [Show-PasswordQuality](Show-PasswordQuality.md)
{{ Fill in the Synopsis }}
### [Start-PasswordSolution](Start-PasswordSolution.md)
Starts Password Expiry Notifications for the whole forest
================================================
FILE: Docs/Show-PasswordQuality.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# Show-PasswordQuality
## SYNOPSIS
{{ Fill in the Synopsis }}
## SYNTAX
```
Show-PasswordQuality [[-Forest] <String>] [[-ExcludeDomains] <String[]>] [[-IncludeDomains] <String[]>]
[[-ExtendedForestInformation] <IDictionary>] [[-FilePath] <String>] [-DontShow] [-Online]
[[-WeakPasswords] <String[]>] [-SeparateDuplicateGroups] [-PassThru] [-AddWorldMap] [[-LogPath] <String>]
[[-LogMaximum] <Int32>] [-LogShowTime] [[-LogTimeFormat] <String>] [<CommonParameters>]
```
## DESCRIPTION
{{ Fill in the Description }}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -Forest
{{ Fill Forest Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases: ForestName
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExcludeDomains
{{ Fill ExcludeDomains Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -IncludeDomains
{{ Fill IncludeDomains Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases: Domain, Domains
Required: False
Position: 3
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ExtendedForestInformation
{{ Fill ExtendedForestInformation Description }}
```yaml
Type: IDictionary
Parameter Sets: (All)
Aliases:
Required: False
Position: 4
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -FilePath
{{ Fill FilePath Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 5
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -DontShow
{{ Fill DontShow Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Online
{{ Fill Online Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -WeakPasswords
{{ Fill WeakPasswords Description }}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: 6
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SeparateDuplicateGroups
If specified, report will show duplicate groups separately, one group per tab.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -PassThru
{{ Fill PassThru Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -AddWorldMap
{{ Fill AddWorldMap Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -LogPath
{{ Fill LogPath Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases: LogFile
Required: False
Position: 7
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -LogMaximum
{{ Fill LogMaximum Description }}
```yaml
Type: Int32
Parameter Sets: (All)
Aliases:
Required: False
Position: 8
Default value: 0
Accept pipeline input: False
Accept wildcard characters: False
```
### -LogShowTime
{{ Fill LogShowTime Description }}
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```
### -LogTimeFormat
{{ Fill LogTimeFormat Description }}
```yaml
Type: String
Parameter Sets: (All)
Aliases:
Required: False
Position: 9
Default value: Yyyy-MM-dd HH:mm:ss
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### None
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
================================================
FILE: Docs/Start-PasswordSolution.md
================================================
---
external help file: PasswordSolution-help.xml
Module Name: PasswordSolution
online version:
schema: 2.0.0
---
# Start-PasswordSolution
## SYNOPSIS
Starts Password Expiry Notifications for the whole forest
## SYNTAX
### DSL (Default)
```
Start-PasswordSolution [[-ConfigurationDSL] <ScriptBlock>] [<CommonParameters>]
```
### Legacy
```
Start-PasswordSolution -EmailParameters <IDictionary> [-OverwriteEmailProperty <String>]
[-OverwriteManagerProperty <String>] -UserSection <IDictionary> -ManagerSection <IDictionary>
-SecuritySection <IDictionary> -AdminSection <IDictionary> -Rules <Array> [-TemplatePreExpiry <ScriptBlock>]
[-TemplatePreExpirySubject <String>] [-TemplatePostExpiry <ScriptBlock>] [-TemplatePostExpirySubject <String>]
-TemplateManager <ScriptBlock> -TemplateManagerSubject <String> -TemplateSecurity <ScriptBlock>
-TemplateSecuritySubject <String> -TemplateManagerNotCompliant <ScriptBlock>
-TemplateManagerNotCompliantSubject <String> -TemplateAdmin <ScriptBlock> -TemplateAdminSubject <String>
[-Logging <IDictionary>] [-HTMLReports <Array>] [-SearchPath <String>] [<CommonParameters>]
```
## DESCRIPTION
Starts Password Expiry Notifications for the whole forest
## EXAMPLES
### EXAMPLE 1
```
An example
```
## PARAMETERS
### -ConfigurationDSL
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: DSL
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -EmailParameters
Parameters for Email.
Uses Mailozaurr splatting behind the scenes, so it supports all options that Mailozaurr does.
```yaml
Type: IDictionary
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteEmailProperty
Property responsible for overwriting the default email field in Active Directory.
Useful when the password notification has to go somewhere else than users email address.
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -OverwriteManagerProperty
{{ Fill OverwriteManagerProperty Description }}
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -UserSection
Parameter description
```yaml
Type: IDictionary
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -ManagerSection
Parameter description
```yaml
Type: IDictionary
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SecuritySection
Parameter description
```yaml
Type: IDictionary
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -AdminSection
Parameter description
```yaml
Type: IDictionary
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Rules
Parameter description
```yaml
Type: Array
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplatePreExpiry
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplatePreExpirySubject
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplatePostExpiry
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplatePostExpirySubject
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateManager
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateManagerSubject
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateSecurity
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateSecuritySubject
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateManagerNotCompliant
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateManagerNotCompliantSubject
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateAdmin
Parameter description
```yaml
Type: ScriptBlock
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -TemplateAdminSubject
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: True
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -Logging
Parameter description
```yaml
Type: IDictionary
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -HTMLReports
Parameter description
```yaml
Type: Array
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -SearchPath
Parameter description
```yaml
Type: String
Parameter Sets: Legacy
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
## OUTPUTS
## NOTES
General notes
## RELATED LINKS
================================================
FILE: Examples/Example-EncryptPassword.ps1
================================================
(Get-Credential -UserName 'test' -Message 'Password').Password | ConvertFrom-SecureString | Set-Clipboard
================================================
FILE: Examples/Example-FindUsers.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$Users = Find-Password -OverwriteEmailProperty 'extensionAttribute7' -OverwriteManagerProperty extensionAttribute1 -FilterOrganizationalUnit @(
"*OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
)
$Users | Format-Table UserPrincipalName, Name, Domain, Type, SamAccountName, OrganizationalUnit, Manager, ManagerEmail, ManagerStatus
#$Users | Sort-Object -Property Manager | Format-Table Name, Manager, ManagerSamAccountName, ManagerEmail, ManagerStatus, ManagerLastLogonDays, ManagerType, Domain, UserPrincipalName
================================================
FILE: Examples/Example-FindUsersAdvanced.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$RuleProperties = @(
'ExtensionAttribute7'
'extensionAttribute7'
'extensionAttribute8'
)
$Users = Find-Password -OverwriteEmailProperty 'extensionAttribute7' -RulesProperties $RuleProperties #| Where-Object { $_.Name -eq 'Test Contact' }
#$Users | Format-Table Name, Extension*, DateExpiry #Manager, ManagerSamAccountName, ManagerEmail, ManagerStatus, ManagerLastLogonDays, ManagerType, Domain, UserPrincipalName
$Users | Select-Object -First 5 | Format-Table Name, Extension*, DateExpiry, LastLogonDate, LastLogonDays
================================================
FILE: Examples/Example-FindUsersEntra.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
Connect-MgGraph -Scopes "User.Read.All" -NoWelcome
$Users = Find-PasswordEntra #-Verbose
#$Users | Format-Table
$Users | Out-HtmlView -ScrollX -Filtering -DataStore JavaScript {
New-HTMLTableCondition -Name 'Enabled' -ComparisonType string -Value $True -BackgroundColor TeaGreen -FailBackgroundColor Salmon
New-HTMLTableCondition -Name 'IsLicensed' -ComparisonType string -Value $True -BackgroundColor TeaGreen -FailBackgroundColor Salmon
New-HTMLTableCondition -Name 'IsSynchronized' -ComparisonType string -Value $True -BackgroundColor TeaGreen -FailBackgroundColor Salmon
New-HTMLTableCondition -Name 'PasswordExpired' -ComparisonType string -Value $false -BackgroundColor TeaGreen -FailBackgroundColor Salmon
} -DisablePaging
================================================
FILE: Examples/Example-FindUsersPasswordQualityConsole.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$Users = Find-PasswordQuality
$Users | Format-Table
#$Users = Find-PasswordQuality -IncludeDomains 'ad.evotec.pl'
#$Users | Format-Table
================================================
FILE: Examples/Example-FindUsersPasswordQualityConsoleWithReplacements.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$Replacements = @(
New-PasswordConfigurationReplacement -PropertyName 'Country' -Type eq -PropertyReplacementHash @{
'PL' = 'Poland'
'DE' = 'Germany'
'AT' = 'Austria'
'IT' = 'Italy'
'Unknown' = 'Not specified in AD'
} -OverwritePropertyName 'CountryCode'
)
$Users = Find-PasswordQuality -Replacements $Replacements
$Users | Format-Table
================================================
FILE: Examples/Example-FindUsersPasswordQualityReport.ps1
================================================
Clear-Host
Import-Module .\PasswordSolution.psd1 -Force
# option 1, one-liner
# Show-PasswordQuality -FilePath C:\Temp\PasswordQuality.html -Online -WeakPasswords "Test1", "Test2", "Test3" -Verbose -SeparateDuplicateGroups -AddWorldMap -PassThru
# option 2, for easier reading with splatting
$showPasswordQualitySplat = @{
FilePath = "$PSScriptRoot\Reporting\PasswordQuality_$(Get-Date -f yyyy-MM-dd_HHmmss).html"
WeakPasswords = "Test1", "Test2", "Test3", 'February2023!#!@ok', $Passwords | ForEach-Object { $_ }
WeakPasswordsHashesFile = 'C:\Support\GitHub\PwnedDatabaseDownloader\pwnedpasswords_ntlm.txt'
WeakPasswordsHashesSortedFile = 'C:\Support\GitHub\PwnedDatabaseDownloader\pwnedpasswords_ntlm.txt'
SeparateDuplicateGroups = $true
PassThru = $true
AddWorldMap = $true
LogPath = "$PSScriptRoot\Logs\PasswordQuality_$(Get-Date -f yyyy-MM-dd_HHmmss).log"
Online = $true
LogMaximum = 5
}
Show-PasswordQuality @showPasswordQualitySplat -Verbose
================================================
FILE: Examples/Example-FindUsersPasswordQualityReportWithReplacements.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$showPasswordQualitySplat = @{
FilePath = "$PSScriptRoot\Reporting\PasswordQuality_$(Get-Date -f yyyy-MM-dd_HHmmss).html"
WeakPasswords = "Test1", "Test2", "Test3", 'February2023!#!@ok', $Passwords | ForEach-Object { $_ }
SeparateDuplicateGroups = $true
PassThru = $true
AddWorldMap = $true
LogPath = "$PSScriptRoot\Logs\PasswordQuality_$(Get-Date -f yyyy-MM-dd_HHmmss).log"
Online = $true
LogMaximum = 5
Replacements = New-PasswordConfigurationReplacement -PropertyName 'ExtensionAttribute4' -Type eq -PropertyReplacementHash @{
'PL' = 'Poland'
'DE' = 'Germany'
'AT' = 'Austria'
'IT' = 'Italy'
'Unknown' = 'Not specified in AD'
} -OverwritePropertyName 'CountriesByExtension'
GroupBy = 'DelegatableAdmins'
}
Show-PasswordQuality @showPasswordQualitySplat -Verbose
================================================
FILE: Examples/Example-PasswordDashboard.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$Passwords = Find-Password
New-HTML {
New-TableOption -DataStore JavaScript -ArrayJoin -BoolAsString
New-HTMLTable -DataTable $Passwords -SearchBuilder -Filtering {
}
} -ShowHTML
================================================
FILE: Examples/Example-PasswordSolution-Entra.ps1
================================================
Clear-Host
Import-Module .\PasswordSolution.psd1 -Force
$Date = Get-Date
Connect-MgGraph -Scopes "User.Read.All" -NoWelcome
Start-PasswordSolution {
$Options = @{
# Logging to file and to screen
ShowTime = $false
LogFile = "$PSScriptRoot\Logs\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).log"
TimeFormat = "yyyy-MM-dd HH:mm:ss"
LogMaximum = 365
NotifyOnSkipUserManagerOnly = $true
NotifyOnSecuritySend = $true
NotifyOnManagerSend = $true
NotifyOnUserSend = $true
NotifyOnUserMatchingRule = $true
NotifyOnUserDaysToExpireNull = $true
NotifyOnUserMatchingRuleForManager = $true
NotifyOnUserMatchingRuleForManagerButNotCompliant = $true
SearchPath = "$PSScriptRoot\Search\SearchLog_$((Get-Date).ToString('yyyy-MM')).xml"
EmailDateFormat = "yyyy-MM-dd"
EmailDateFormatUTCConversion = $true
# FilterOrganizationalUnit = @(
# "*OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
# "*OU=Administration,DC=ad,DC=evotec,DC=xyz"
# )
}
New-PasswordConfigurationOption @Options
New-PasswordConfigurationEntra -Enable
$GraphCredentials = @{
ClientID = '0fb383f1-8bfe-4c68-8ce2-5f6aa1d602fe'
DirectoryID = 'ceb371f6-8745-4876-a040-69f2d10a9d1a'
ClientSecret = Get-Content -Raw -LiteralPath "C:\Support\Important\O365-GraphEmailTestingKey.txt"
}
# (full support for Mailozaurr parameters)
$EmailParameters = @{
Credential = ConvertTo-GraphCredential -ClientID $GraphCredentials.ClientID -ClientSecret $GraphCredentials.ClientSecret -DirectoryID $GraphCredentials.DirectoryID
Graph = $true
Priority = 'Normal'
From = 'przemyslaw.klys@test.pl'
WhatIf = $true
ReplyTo = 'contact+testgithub@test.pl'
}
New-PasswordConfigurationEmail @EmailParameters
# Configure behavior for different types of actions
New-PasswordConfigurationType -Type User -Enable -SendCountMaximum 10 -DefaultEmail 'przemyslaw.klys+testgithub1@evotec.pl'
New-PasswordConfigurationType -Type Manager -Enable -SendCountMaximum 10 -DefaultEmail 'przemyslaw.klys+testgithub2@evotec.pl'
New-PasswordConfigurationType -Type Security -Enable -SendCountMaximum 1 -DefaultEmail 'przemyslaw.klys+testgithub3@evotec.pl' #-AttachCSV
# Configure reporting
$Report = [ordered] @{
Enable = $true
ShowHTML = $true
Title = "Password Solution Summary"
Online = $true
DisableWarnings = $true
ShowConfiguration = $true
ShowAllUsers = $true
ShowRules = $true
ShowUsersSent = $true
ShowManagersSent = $true
ShowEscalationSent = $true
ShowSkippedUsers = $false
ShowSkippedLocations = $false
ShowSearchUsers = $true
ShowSearchManagers = $true
ShowSearchEscalations = $true
NestedRules = $false
FilePath = "$PSScriptRoot\Reporting\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html"
AttachToEmail = $true
}
New-PasswordConfigurationReport @Report
# Configure rules for different types of users
# New-PasswordConfigurationRule -Name 'Administrative Accounts' -Enable -IncludeExpiring -IncludePasswordNeverExpires -PasswordNeverExpiresDays 90 {
# # follow expiration days of a user
# New-PasswordConfigurationRuleReminder -Type 'Manager'
# # use a custom expiration days, and send only on specific days 1st, 10th and 15th of a month
# New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfMonth 1, 10, 15 -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
# # use a custom expiration days (only if it's less then 10 days left), and send only on specific days of a week
# New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfWeek Monday, Wednesday, Friday -ExpirationDays 10 -ComparisonType 'lt'
# } -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60 -IncludeNameProperties 'SamAccountName' -IncludeName = @(
# "ADM_*"
# "SADM_*"
# "PADM_*"
# "MADM_*"
# "NADM_*"
# "ADM0_*"
# "ADM1_*"
# "ADM2_*"
# )
# Configure rules for different types of users
$newPasswordConfigurationRuleSplat = @{
Name = 'Administrative Accounts'
Enable = $true
IncludeExpiring = $true
IncludePasswordNeverExpires = $true
PasswordNeverExpiresDays = 90
ReminderConfiguration = {
# follow expiration days of a user
New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfWeek Monday, Wednesday, Friday -ExpirationDays 60 -ComparisonType lt #-ExpirationDays @(-200..-1), 0, 1, 2, 3, 7, 15, 30, 60 -ComparisonType lt
New-PasswordConfigurationRuleReminder -Type 'ManagerNotCompliant' -DayOfWeek Friday -ExpirationDays 300 -ComparisonType lt
New-PasswordConfigurationRuleReminder -Type 'Security' -DayOfWeek Monday -ExpirationDays -1 -ComparisonType lt
}
#ReminderDays = '-45', '-30', '-15', '-7' #, 0, 1, 2, 3, 7, 15, 30, 60, 29, 28
# IncludeOU = @(
# "*OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
# "*OU=Administration,DC=ad,DC=evotec,DC=xyz"
# )
IncludeName = @(
'Przem*'
)
IncludeNameProperties = 'DisplayName', 'SamAccountName'
ManagerReminder = $true
ProcessManagersOnly = $true
ManagerNotCompliant = $true
ManagerNotCompliantDisplayName = 'Global Service Desk'
ManagerNotCompliantEmailAddress = 'przemyslaw.klys@test.pl'
ManagerNotCompliantDisabled = $true
ManagerNotCompliantMissing = $true
ManagerNotCompliantMissingEmail = $true
ManagerNotCompliantLastLogonDays = 90
SecurityEscalation = $true
SecurityEscalationDisplayName = 'IT Security'
SecurityEscalationEmailAddress = 'przemyslaw.klys@test.pl'
}
New-PasswordConfigurationRule @newPasswordConfigurationRuleSplat
# New-PasswordConfigurationRule -Name 'All others' -Enable -ReminderDays @(500..-500), 60, 59, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45 {
# # follow expiration days of a user, you need to enable ManagerReminder for this functionality to work
# New-PasswordConfigurationRuleReminder -Type 'Manager' -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
# # use a custom expiration days, and send only on specific days 1st, 10th and 15th of a month
# New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfMonth 1, 10, 15 -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
# # use a custom expiration days (only if it's less then 10 days left), and send only on specific days of a week
# New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfWeek Monday, Wednesday, Friday -ExpirationDays 10 -ComparisonType 'lt'
# } -IncludeExpiring -OverwriteEmailProperty 'extensionAttribute5' -OverwriteManagerProperty 'extensionAttribute1' -ManagerReminder
# Template to user when sending email to user before password expires
New-PasswordConfigurationTemplate -Type PreExpiry -Template {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Dear ", "$DisplayName," -LineBreak
EmailText -Text "Your password will expire in $DaysToExpire days and if you do not change it, you will not be able to connect to the Evotec Network and IT services. "
EmailText -Text "Depending on your situation, please follow one of the methods below to change your password." -LineBreak
EmailText -Text "If you are connected to the Evotec Network (either directly or through VPN):"
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "Type in your old password and then type the new one according to the Policy (at least 8 characters, at least one uppercase letter, at least one lowercase letter, at least one number, at least one special character)"
EmailListItem -Text "After the change is complete you will be prompted with information that the password has been changed"
}
EmailText -Text "If you are not connected to the Evotec Network:"
EmailList {
EmailListItem -Text "Open [Password Change Link](https://account.activedirectory.windowsazure.com/ChangePassword.aspx) using your web browser"
EmailListItem -Text "Login using your current credentials"
EmailListItem -Text "On the change password form, type your old password and the new password that you want to set (twice)"
EmailListItem -Text "Click Submit"
}
EmailText -Text "Please also remember to modify your password on the email configuration of your Smartphone or Tablet." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject '[Password Expiring] Your password will expire on $DateExpiry ($DaysToExpire days)'
# Template to user when sending email to user after password expires
New-PasswordConfigurationTemplate -Type PostExpiry -Template {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Dear ", "$DisplayName," -LineBreak
EmailText -Text "Your password already expired on $PasswordLastSet. If you do not change it, you will not be able to connect to the Evotec Network and IT services. "
EmailText -Text "Depending on your situation, please follow one of the methods below to change your password." -LineBreak
EmailText -Text "If you are connected to the Evotec Network (either directly or through VPN):"
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "Type in your old password and then type the new one according to the Policy"
EmailListItem -Text "After the change is complete you will be prompted with information that the password has been changed"
}
EmailText -Text "If you are not connected to the Evotec Network:"
EmailList {
EmailListItem -Text "Open [Password Change Link](https://account.activedirectory.windowsazure.com/ChangePassword.aspx) using your web browser"
EmailListItem -Text "Login using your current credentials"
EmailListItem -Text "On the change password form, type your old password and the new password that you want to set (twice)"
EmailListItem -Text "Click Submit"
}
EmailText -Text "Please also remember to modify your password on the email configuration of your Smartphone or Tablet." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject '[Password Expiring] Your password expired on $DateExpiry ($DaysToExpire days ago)'
# Template to security team with all service accounts that have expired passwords and password never expires set to true
New-PasswordConfigurationTemplate -Type Security {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello ", "$ManagerDisplayName", "," -LineBreak -FontWeight normal, bold, normal
EmailText -Text "Below is a summary of ", "all service accounts", " where the passwords have exceeded the time limit stipulated in the password policy KGD. These accounts are all in violation of the KGD and immediate action/escalation should take place." -LineBreak -FontWeight normal, bold, normal
EmailText -Text "It has been agreed that the ", "password never expires", " flag has been set to ", "true", " to avoid business disruption/loss of service. As a result we require your escalation to the managers of the account to take immediate action to change the password ASAP." -LineBreak -FontWeight normal, bold, normal, bold, normal
EmailText -Text "Numerous automated reminders have been sent to the Manager, but no response/action has been taken yet." -LineBreak
EmailText -Text "Please reach out directly to the manager/site to ensure that these passwords are changed immediately." -LineBreak
EmailText -Text "If there is still lack of responses/action taken, it will be in your (IT Security) discretion to disable the account(s) question and take any appropriate action." -LineBreak -FontWeight bold
EmailTable -DataTable $ManagerUsersTable -HideFooter
EmailText -LineBreak
EmailText -Text "Many thanks in advance." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject "[Passsword Expired] Following accounts are expired!"
# Template to manager with all accounts that have expired passwords
New-PasswordConfigurationTemplate -Type Manager {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Below is a summary of accounts where the password is due to expire soon. These accounts are either:"
EmailList {
EmailListItem -Text 'Managed by you'
EmailListItem -Text 'You are the manager of the owner of these accounts.'
}
EmailText -Text "Where you are the owner, please action the password change on each account outlined below, according to the rules specified by Password Policy." -LineBreak
EmailTable -DataTable $ManagerUsersTable -HideFooter
EmailText -LineBreak
EmailText -Text @(
"Please note that for Service Accounts, even though the ",
"'password never expires' "
"flag remains set to "
"'true' "
", the password MUST be changed before the expiry date specified in the above table. "
"It is the responsibility of the manager of the account to ensure that this takes place. "
) -FontWeight normal, bold, normal, bold, normal, normal -LineBreak
EmailText -Text @(
"Please make an effort "
"to change password yourself using known methods rather than asking the Service Desk to change the password for you. "
"If password is changed by Service Desk agent, there are at least 2 people knowing the password - Service Desk Agent and You! "
"Do you really want the Service Desk agent to know the password to critical system you manage/own? "
"Be responsible!"
) -FontWeight bold, normal, normal, normal, bold -LineBreak -Color None, None, None, None, Red
EmailText -Text "One of the ways to change the password is: " -FontWeight bold
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "In the account name - change it to the account you want to change password for." -FontWeight bold
EmailListItem -Text "Type in current password for the account and then type the new one according to the rules specified in the password policy."
EmailListItem -Text "After the change is complete you will be provided with information that the password has been changed"
}
EmailText -Text "Failure to take action could result in loss of service/escalation to the IT Security team." -LineBreak -FontWeight bold
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject "[Passsword Expiring] Accounts you manage/own are expiring or already expired"
# Template to Service Desk with information about manager missing, disabled, last logon >90 days, missing email for service accounts
New-PasswordConfigurationTemplate -Type ManagerNotCompliant {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Below is a summary of accounts where there is missing 'critical' information. These accounts are either:"
EmailList {
EmailListItem -Text "Missing a Manager in the AD - please add an active manager"
EmailListItem -Text "The Manager in AD is Disabled - please add an active manager"
EmailListItem -Text "Manager Last logon >90 days - please confirm if the manager is still an employee at Evotec/change the manager to an active manager"
EmailListItem -Text "Manager is missing email - add manager email"
}
EmailText -Text "Please contact the respective local IT Service Desk (outlined in the below table) to update this Manager's attributes in the AD directly. The suggested action to take can be found in the below table." -LineBreak
EmailTable -DataTable $ManagerUsersTableManagerNotCompliant -HideFooter
EmailText -LineBreak
EmailText -Text "Please note that all Service Accounts must have a Manager set in the AD, in order to fall within the Password Policy compliance notifications that are sent globally." -LineBreak
EmailText -Text "Kind regards," -LineBreak
EmailText -Text "IT Service Desk" -LineBreak
} -Subject "[Password Escalation] Accounts are expiring with non-compliant manager"
# Template to Admins with information summarizing what happened
New-PasswordConfigurationTemplate -Type Admin {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Here's the summary of password notifications:"
EmailList {
EmailListItem -Text "Found users matching rule to send emails: ", $SummaryUsersEmails.Count
EmailListItem -Text "Sent emails to users: ", ($SummaryUsersEmails | Where-Object { $_.Status -eq $true }).Count
EmailListItem -Text "Couldn't send emails because of no email: ", ($SummaryUsersEmails | Where-Object { $_.Status -eq $false -and $_.StatusError -eq 'No email address for user' }).Count
EmailListItem -Text "Couldn't send emails because other reasons: ", ($SummaryUsersEmails | Where-Object { $_.Status -eq $false -and $_.StatusError -ne 'No email address for user' }).Count
EmailListItem -Text "Sent emails to managers: ", $SummaryManagersEmails.Count
EmailListItem -Text "Sent emails to security: ", $SummaryEscalationEmails.Count
}
EmailText -Text "It took ", $TimeToProcess , " seconds to process the template." -LineBreak
EmailText -Text "Hope everything works correctly! ", " You can take a look at [Password Solution Report](https://adcompliance.Evotec.local/CustomReports/PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html) for details." -LineBreak
EmailText -Text "Kind regards," -LineBreak
EmailText -Text "IT Service Desk" -LineBreak
} -Subject '[Password Summary] Passwords summary'
}
================================================
FILE: Examples/Example-PasswordSolution-LegacyConfiguration01.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
$Date = Get-Date
$GraphCredentials = @{
ClientID = '0fb383f1-8bfe-4c68-8ce2-5f6aa1d602fe'
DirectoryID = 'ceb371f6-8745-4876-a040-69f2d10a9d1a'
ClientSecret = Get-Content -Raw -LiteralPath "C:\Support\Important\O365-GraphEmailTestingKey.txt"
}
$PasswordSolution = [ordered] @{
# Graph based credentials (full support for Mailozaurr parameters)
EmailParameters = @{
Credential = ConvertTo-GraphCredential -ClientID $GraphCredentials.ClientID -ClientSecret $GraphCredentials.ClientSecret -DirectoryID $GraphCredentials.DirectoryID
Graph = $true
Priority = 'Normal'
From = 'przemyslaw.klys+testgithub@evotec.pl'
WhatIf = $false
ReplyTo = 'contact+testgithub@evotec.pl'
}
# Standard SMTP credentials (full support for Mailozaurr parameters)
# EmailParameters = [ordered] @{
# UserName = 'ADAutomations@evotec.pl'
# Password = Get-Content -LiteralPath D:\Secrets\WO_SVC_ADAutomations.txt
# From = 'ADAutomations@evotec.pl'
# Server = 'smtp.office365.com'
# Priority = 'High'
# UseSsl = $true
# Port = 587
# Verbose = $false
# WhatIf = $true
# AsSecureString = $true
# }
OverwriteEmailProperty = 'extensionAttribute13'
UserSection = @{
Enable = $true
SendCountMaximum = 3
SendToDefaultEmail = $true # if enabled $EmailParameters are used (good for testing)
DefaultEmail = 'przemyslaw.klys+testgithub@evotec.pl' # your default email field (IMPORTANT)
}
ManagerSection = @{
Enable = $true
SendCountMaximum = 3
SendToDefaultEmail = $true # if enabled $EmailParameters are used (good for testing)
DefaultEmail = 'przemyslaw.klys+testgithub@evotec.pl' # your default email field (IMPORTANT)
}
SecuritySection = @{
Enable = $true
SendCountMaximum = 3
SendToDefaultEmail = $true # if enabled $EmailParameters are used (good for testing)
DefaultEmail = 'przemyslaw.klys+testgithub@evotec.pl' # your default email field (IMPORTANT)
AttachCSV = $true
}
AdminSection = @{
Enable = $true # doesn't processes this section at all
Email = 'przemyslaw.klys+testgithub@evotec.pl'
Subject = "[Reporting Evotec] Summary of password reminders"
Manager = [ordered] @{
DisplayName = 'Administrators'
EmailAddress = 'przemyslaw.klys+testgithub@evotec.pl'
}
}
Rules = @(
# rules are new way to define things. You can define more than one rule and limit it per group/ou
# the primary rule above can be set or doesn't have to, all parameters from rules below can be used across different rules
# only one email will be sent even if the rules are overlapping, the first one wins
#region "admins"
[ordered] @{
Name = 'Administrative Accounts'
Enable = $false # doesn't processes this section at all if $false
Reminders = -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
#Reminders = @(-200..-1), 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 28, 30, @(30..60), @(61..370)
# this means we want to process only users that NeverExpire
IncludeExpiring = $true
IncludePasswordNeverExpires = $true
PasswordNeverExpiresDays = 90
IncludeNameProperties = 'SamAccountName'
IncludeName = @(
"ADM_*"
"SADM_*"
"PADM_*"
"MADM_*"
"NADM_*"
"ADM0_*"
"ADM1_*"
"ADM2_*"
)
SendToManager = @{
Manager = [ordered] @{
Enable = $true
Reminders = @{
OnDay = @{
Enable = $true
Days = 'Monday'
Reminder = 10
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
# Manager not compliant will be processed regardless of Reminder for Users
ManagerNotCompliant = [ordered] @{
Enable = $false
Manager = [ordered] @{
DisplayName = 'Global Service Desk'
EmailAddress = 'servicedesk@evotec.pl'
}
Disabled = $true
Missing = $true
MissingEmail = $true
LastLogon = $true
LastLogonDays = 90
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 10, 21
Reminder = 50
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
}
}
#endregion admins
#region "ITR01"
[ordered] @{
Name = 'ITR01 SVC'
Enable = $false # doesn't processes this section at all if $false
Reminders = -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
IncludeExpiring = $true
IncludePasswordNeverExpires = $true
PasswordNeverExpiresDays = 360
IncludeNameProperties = 'DisplayName', 'SamAccountName', 'Name', 'UserPrincipalName'
IncludeName = @(
"*SVC_*"
)
# limit group or limit OU can limit people with password never expire to certain users only
IncludeOU = @(
'*OU=ITR01,DC=*'
)
# It's important to use single quotes to not activate variables
SendToManager = @{
Manager = [ordered] @{
Enable = $true
# it uses manager from AD in this section
Reminders = @{
Default = @{
Enable = $true
}
OnDay = @{
Enable = $true
Days = 'Monday', 'Thursday'
Reminder = 15
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
# Security escalation will be processed regardless of Reminder for Users
# Meaning Reminders definded below can be different then what users get
SecurityEscalation = [ordered] @{
Enable = $true
Manager = [ordered] @{
DisplayName = 'IT Security'
EmailAddress = 'security@evotec.pl'
}
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 10, 21
Reminder = -1
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
# Manager not compliant will be processed regardless of Reminder for Users
ManagerNotCompliant = [ordered] @{
Enable = $true
Manager = [ordered] @{
DisplayName = 'ITR01 Service Desk'
EmailAddress = 'przemyslaw.klys+testgithub@evotec.pl'
}
Disabled = $true
Missing = $true
MissingEmail = $true
LastLogon = $true
LastLogonDays = 90
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 10, 21
Reminder = 50
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
}
}
[ordered] @{
Name = 'ITR01 USR'
Enable = $false # doesn't processes this section at all if $false
Reminders = -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
#Reminders = @(-200..-1), 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 28, 30, @(30..60), @(61..370)
# this means we want to process only users that NeverExpire
IncludeExpiring = $true
IncludePasswordNeverExpires = $true
PasswordNeverExpiresDays = 360
IncludeNameProperties = 'DisplayName', 'SamAccountName', 'Name', 'UserPrincipalName'
IncludeName = @(
"*_USR_*"
)
# limit group or limit OU can limit people with password never expire to certain users only
IncludeOU = @(
'*OU=ITR01,DC=*'
)
SendToManager = @{
Manager = [ordered] @{
Enable = $true
Reminders = @{
Default = @{
Enable = $true
}
OnDay = @{
Enable = $true
Days = 'Monday', 'Thursday'
Reminder = 15
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
# Security escalation will be processed regardless of Reminder for Users
# Meaning Reminders definded below can be different then what users get
SecurityEscalation = [ordered] @{
Enable = $false
Manager = [ordered] @{
DisplayName = 'IT Security'
EmailAddress = 'security@evotec.pl'
}
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 10, 21
Reminder = -1
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
ManagerNotCompliant = [ordered] @{
Enable = $false
Manager = [ordered] @{
DisplayName = 'ITR01 Service Desk'
EmailAddress = 'przemyslaw.klys+testgithub@evotec.pl'
}
Disabled = $true
Missing = $true
MissingEmail = $true
LastLogon = $true
LastLogonDays = 90
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 10, 21
Reminder = 50
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
}
}
# [ordered] @{
# Name = 'ITR01'
# Enable = $true # doesn't processes this section at all if $false
# Reminders = 60, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45
# # this means we want to process only users that NeverExpire
# IncludeExpiring = $true
# # limit group or limit OU can limit people with password never expire to certain users only
# IncludeOU = @(
# '*OU=ITR01,DC=*'
# )
# }
[ordered] @{
Name = 'ITR01'
Enable = $true # doesn't processes this section at all if $false
Reminders = 60, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45
# this means we want to process only users that NeverExpire
IncludeExpiring = $true
# limit group or limit OU can limit people with password never expire to certain users only
IncludeOU = @(
'*OU=ITR01,DC=*'
)
IncludeNameProperties = 'SamAccountName'
IncludeName = @(
"HACO"
)
SendToManager = @{
Manager = [ordered] @{
Enable = $true
Reminders = @{
Default = @{
Enable = $true
}
OnDay = @{
Enable = $true
Days = 'Monday', 'Thursday'
Reminder = 15
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
}
}
#endregion
#region "All others"
[ordered] @{
Name = 'All others'
Enable = $true # doesn't processes this section at all if $false
Reminders = @(500..-500), 60, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45
IncludeExpiring = $true
OverwriteEmailProperty = 'extensionAttribute5'
SendToManager = @{
Manager = [ordered] @{
Enable = $true
# it uses manager from AD in this section
Reminders = @{
Default = @{
Enable = $true
}
OnDay = @{
Enable = $true
Days = 'Monday', 'Thursday'
Reminder = 15
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
# Security escalation will be processed regardless of Reminder for Users
# Meaning Reminders definded below can be different then what users get
SecurityEscalation = [ordered] @{
Enable = $true
Manager = [ordered] @{
DisplayName = 'IT Security'
EmailAddress = 'przemyslaw.klys+testgithub@evotec.pl'
}
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 1, 21
Reminder = -1
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
# Manager not compliant will be processed regardless of Reminder for Users
ManagerNotCompliant = [ordered] @{
Enable = $true
Manager = [ordered] @{
DisplayName = 'ITR01 Service Desk'
EmailAddress = 'przemyslaw.klys+testgithub@evotec.pl'
}
Disabled = $true
Missing = $true
MissingEmail = $true
LastLogon = $true
LastLogonDays = 90
Reminders = @{
OnDayOfMonth = @{
Enable = $true
Days = 1, 21
Reminder = 50
ComparisonType = 'lt' # lt = less then, gt = greater then, eq = equal, in = inside
}
}
}
}
}
#endregion "All others"
)
# Keep in mind those are script block not hashtable
TemplatePreExpiry = {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Dear ", "$DisplayName," -LineBreak
EmailText -Text "Your password will expire in $DaysToExpire days and if you do not change it, you will not be able to connect to the Evotec Network and IT services. "
EmailText -Text "Depending on your situation, please follow one of the methods below to change your password." -LineBreak
EmailText -Text "If you are connected to the Evotec Network (either directly or through VPN):"
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "Type in your old password and then type the new one according to the [KGD: 2-96-IS-POL-01113513.](http://search.evotec.local/Open/2-96-IS-POL-01113513)"
EmailListItem -Text "After the change is complete you will be prompted with information that the password has been changed"
}
EmailText -Text "If you are not connected to the Evotec Network:"
EmailList {
EmailListItem -Text "Open [Password Change Link](https://account.activedirectory.windowsazure.com/ChangePassword.aspx) using your web browser"
EmailListItem -Text "Login using your current credentials"
EmailListItem -Text "On the change password form, type your old password and the new password that you want to set (twice)"
EmailListItem -Text "Click Submit"
}
EmailText -Text "Please also remember to modify your password on the email configuration of your Smartphone or Tablet." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
}
TemplatePreExpirySubject = '[Password Expiring] Your password will expire on $DateExpiry ($DaysToExpire days)'
TemplatePostExpiry = {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Dear ", "$DisplayName," -LineBreak
EmailText -Text "Your password already expired on $PasswordLastSet. If you do not change it, you will not be able to connect to the Evotec Network and IT services. "
EmailText -Text "Depending on your situation, please follow one of the methods below to change your password." -LineBreak
EmailText -Text "If you are connected to the Evotec Network (either directly or through VPN):"
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "Type in your old password and then type the new one according to the [KGD: 2-96-IS-POL-01113513.](http://search.Evotec.local/Open/2-96-IS-POL-01113513)"
EmailListItem -Text "After the change is complete you will be prompted with information that the password has been changed"
}
EmailText -Text "If you are not connected to the Evotec Network:"
EmailList {
EmailListItem -Text "Open [Password Change Link](https://account.activedirectory.windowsazure.com/ChangePassword.aspx) using your web browser"
EmailListItem -Text "Login using your current credentials"
EmailListItem -Text "On the change password form, type your old password and the new password that you want to set (twice)"
EmailListItem -Text "Click Submit"
}
EmailText -Text "Please also remember to modify your password on the email configuration of your Smartphone or Tablet." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
}
TemplatePostExpirySubject = '[Password Expiring] Your password expired on $DateExpiry ($DaysToExpire days ago)'
TemplateManager = {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Below is a summary of accounts where the password is due to expire soon. These accounts are either:"
EmailList {
EmailListItem -Text 'Managed by you'
EmailListItem -Text 'You are the manager of the owner of these accounts.'
}
EmailText -Text "Where you are the owner, please action the password change on each account outlined below, according to the rules specified by Password Policy [KGD: 2-96-IS-POL-01113513](http://search.Evotec.local/Open/2-96-IS-POL-01113513)." -LineBreak
EmailTable -DataTable $ManagerUsersTable -HideFooter
EmailText -LineBreak
EmailText -Text @(
"Please note that for Service Accounts, even though the ",
"'password never expires' "
"flag remains set to "
"'true' "
", the password MUST be changed before the expiry date specified in the above table. "
"It is the responsibility of the manager of the account to ensure that this takes place. "
) -FontWeight normal, bold, normal, bold, normal, normal -LineBreak
EmailText -Text @(
"Please make an effort "
"to change password yourself using known methods rather than asking the Service Desk to change the password for you. "
"If password is changed by Service Desk agent, there are at least 2 people knowing the password - Service Desk Agent and You! "
"Do you really want the Service Desk agent to know the password to critical system you manage/own? "
"Be responsible!"
) -FontWeight bold, normal, normal, normal, bold -LineBreak -Color None, None, None, None, Red
EmailText -Text "One of the ways to change the password is: " -FontWeight bold
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "In the account name - change it to the account you want to change password for." -FontWeight bold
EmailListItem -Text "Type in current password for the account and then type the new one according to the rules specified in the password policy: [KGD: 2-96-IS-POL-01113513.](http://search.Evotec.local/Open/2-96-IS-POL-01113513)"
EmailListItem -Text "After the change is complete you will be provided with information that the password has been changed"
}
EmailText -Text "Failure to take action could result in loss of service/escalation to the IT Security team." -LineBreak -FontWeight bold
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
}
TemplateManagerSubject = "[Passsword Expiring] Accounts you manage/own are expiring or already expired"
TemplateSecurity = {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello ", "$ManagerDisplayName", "," -LineBreak -FontWeight normal, bold, normal
EmailText -Text "Below is a summary of ", "all service accounts", " where the passwords have exceeded the time limit stipulated in the password policy KGD. These accounts are all in violation of the KGD and immediate action/escalation should take place." -LineBreak -FontWeight normal, bold, normal
EmailText -Text "It has been agreed that the ", "password never expires", " flag has been set to ", "true", " to avoid business disruption/loss of service. As a result we require your escalation to the managers of the account to take immediate action to change the password ASAP." -LineBreak -FontWeight normal, bold, normal, bold, normal
EmailText -Text "Numerous automated reminders have been sent to the Manager, but no response/action has been taken yet." -LineBreak
EmailText -Text "Please reach out directly to the manager/site to ensure that these passwords are changed immediately." -LineBreak
EmailText -Text "If there is still lack of responses/action taken, it will be in your (IT Security) discretion to disable the account(s) question and take any appropriate action." -LineBreak -FontWeight bold
EmailTable -DataTable $ManagerUsersTable -HideFooter
EmailText -LineBreak
EmailText -Text "Many thanks in advance." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
}
TemplateSecuritySubject = "[Passsword Expired] Following accounts are expired!"
TemplateManagerNotCompliant = {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Below is a summary of accounts where there is missing 'critical' information. These accounts are either:"
EmailList {
EmailListItem -Text "Missing a Manager in the AD - please add an active manager"
EmailListItem -Text "The Manager in AD is Disabled - please add an active manager"
EmailListItem -Text "Manager Last logon >90 days - please confirm if the manager is still an employee at Evotec/change the manager to an active manager"
EmailListItem -Text "Manager is missing email - add manager email"
}
EmailText -Text "Please contact the respective local IT Service Desk (outlined in the below table) to update this Manager's attributes in the AD directly. The suggested action to take can be found in the below table." -LineBreak
EmailTable -DataTable $ManagerUsersTableManagerNotCompliant -HideFooter
EmailText -LineBreak
EmailText -Text "Please note that all Service Accounts must have a Manager set in the AD, in order to fall within the Password Policy compliance notifications that are sent globally." -LineBreak
EmailText -Text "Kind regards," -LineBreak
EmailText -Text "IT Service Desk" -LineBreak
}
TemplateManagerNotCompliantSubject = "[Password Escalation] Accounts are expiring with non-compliant manager"
TemplateAdmin = {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Here's the summary of password notifications:"
EmailList {
EmailListItem -Text "Found users matching rule to send emails: ", $SummaryUsersEmails.Count
EmailListItem -Text "Sent emails to users: ", ($SummaryUsersEmails | Where-Object { $_.Status -eq $true }).Count
EmailListItem -Text "Couldn't send emails because of no email: ", ($SummaryUsersEmails | Where-Object { $_.Status -eq $false -and $_.StatusError -eq 'No email address for user' }).Count
EmailListItem -Text "Couldn't send emails because other reasons: ", ($SummaryUsersEmails | Where-Object { $_.Status -eq $false -and $_.StatusError -ne 'No email address for user' }).Count
EmailListItem -Text "Sent emails to managers: ", $SummaryManagersEmails.Count
EmailListItem -Text "Sent emails to security: ", $SummaryEscalationEmails.Count
}
EmailText -Text "It took ", $TimeToProcess , " seconds to process the template." -LineBreak
EmailText -Text "Hope everything works correctly! ", " You can take a look at [Password Solution Report](https://adcompliance.Evotec.local/CustomReports/PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html) for details." -LineBreak
EmailText -Text "Kind regards," -LineBreak
EmailText -Text "IT Service Desk" -LineBreak
}
TemplateAdminSubject = '[Password Summary] Passwords summary'
Logging = @{
# Logging to file and to screen
ShowTime = $true
LogFile = "$PSScriptRoot\Logs\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).log"
TimeFormat = "yyyy-MM-dd HH:mm:ss"
LogMaximum = 365
NotifyOnSkipUserManagerOnly = $false
NotifyOnSecuritySend = $true
NotifyOnManagerSend = $true
NotifyOnUserSend = $true
NotifyOnUserMatchingRule = $true
NotifyOnUserDaysToExpireNull = $true
EmailDateFormat = "yyyy-MM-dd HH:mm:ss"
EmailDateFormatUTCConversion = $true
}
HTMLReports = @(
# Accepts a list of reports to generate. Can be multiple reprorts having different sections, or just one having it all
[ordered] @{
Enable = $true
ShowHTML = $true
Title = "Password Solution Summary"
Online = $true
DisableWarnings = $true
ShowConfiguration = $true
ShowAllUsers = $true
ShowRules = $true
ShowUsersSent = $true
ShowManagersSent = $true
ShowEscalationSent = $true
ShowSkippedUsers = $true
ShowSkippedLocations = $true
ShowSearchUsers = $true
ShowSearchManagers = $true
ShowSearchEscalations = $true
NestedRules = $false
FilePath = "$PSScriptRoot\Reporting\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html"
AttachToEmail = $true
}
)
SearchPath = "$PSScriptRoot\Search\SearchLog_$((Get-Date).ToString('yyyy-MM')).xml"
}
Start-PasswordSolution @PasswordSolution
================================================
FILE: Examples/Example-PasswordSolution-ModernConfiguration01.ps1
================================================
Clear-Host
Import-Module .\PasswordSolution.psd1 -Force
$Date = Get-Date
Start-PasswordSolution {
$Options = @{
# Logging to file and to screen
ShowTime = $false
LogFile = "$PSScriptRoot\Logs\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).log"
TimeFormat = "yyyy-MM-dd HH:mm:ss"
LogMaximum = 365
NotifyOnSkipUserManagerOnly = $true
NotifyOnSecuritySend = $true
NotifyOnManagerSend = $true
NotifyOnUserSend = $true
NotifyOnUserMatchingRule = $true
NotifyOnUserDaysToExpireNull = $true
NotifyOnUserMatchingRuleForManager = $true
NotifyOnUserMatchingRuleForManagerButNotCompliant = $true
SearchPath = "$PSScriptRoot\Search\SearchLog_$((Get-Date).ToString('yyyy-MM')).xml"
EmailDateFormat = "yyyy-MM-dd"
EmailDateFormatUTCConversion = $true
FilterOrganizationalUnit = @(
"*OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
"*OU=Administration,DC=ad,DC=evotec,DC=xyz"
)
# Using SearchBase is risky, as it can lead to missing managers "connection" to users, which may be filtered out
# If you use Manager functionality use FilterOrganizationalUnit instead, unless you're sure what you're doing
#SearchBase = @(
# "OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
# "OU=Administration,DC=ad,DC=evotec,DC=xyz"
#)
}
New-PasswordConfigurationOption @Options
$GraphCredentials = @{
ClientID = '0fb383f1-8bfe-4c68-8ce2-5f6aa1d602fe'
DirectoryID = 'ceb371f6-8745-4876-a040-69f2d10a9d1a'
ClientSecret = Get-Content -Raw -LiteralPath "C:\Support\Important\O365-GraphEmailTestingKey.txt"
}
# (full support for Mailozaurr parameters)
$EmailParameters = @{
Credential = ConvertTo-GraphCredential -ClientID $GraphCredentials.ClientID -ClientSecret $GraphCredentials.ClientSecret -DirectoryID $GraphCredentials.DirectoryID
Graph = $true
Priority = 'Normal'
From = 'przemyslaw.klys@test.pl'
WhatIf = $true
ReplyTo = 'contact+testgithub@test.pl'
}
New-PasswordConfigurationEmail @EmailParameters
# Configure behavior for different types of actions
New-PasswordConfigurationType -Type User -Enable -SendCountMaximum 10 -DefaultEmail 'przemyslaw.klys+testgithub1@test.pl'
New-PasswordConfigurationType -Type Manager -Enable -SendCountMaximum 10 -DefaultEmail 'przemyslaw.klys+testgithub2@test.pl'
New-PasswordConfigurationType -Type Security -Enable -SendCountMaximum 1 -DefaultEmail 'przemyslaw.klys+testgithub3@test.pl' -AttachCSV
New-PasswordConfigurationType -Type Admin -Enable -EmailAddress 'przemyslaw.klys+testgithub3@test.pl' -DisplayName 'Administrators'
# Configure reporting
$Report = [ordered] @{
Enable = $true
ShowHTML = $true
Title = "Password Solution Summary"
Online = $true
DisableWarnings = $true
ShowConfiguration = $true
ShowAllUsers = $true
ShowRules = $true
ShowUsersSent = $true
ShowManagersSent = $true
ShowEscalationSent = $true
ShowSkippedUsers = $false
ShowSkippedLocations = $false
ShowSearchUsers = $true
ShowSearchManagers = $true
ShowSearchEscalations = $true
NestedRules = $false
FilePath = "$PSScriptRoot\Reporting\PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html"
AttachToEmail = $true
}
New-PasswordConfigurationReport @Report
# Configure rules for different types of users
# New-PasswordConfigurationRule -Name 'Administrative Accounts' -Enable -IncludeExpiring -IncludePasswordNeverExpires -PasswordNeverExpiresDays 90 {
# # follow expiration days of a user
# New-PasswordConfigurationRuleReminder -Type 'Manager'
# # use a custom expiration days, and send only on specific days 1st, 10th and 15th of a month
# New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfMonth 1, 10, 15 -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60
# # use a custom expiration days (only if it's less then 10 days left), and send only on specific days of a week
# New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfWeek Monday, Wednesday, Friday -ExpirationDays 10 -ComparisonType 'lt'
# } -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60 -IncludeNameProperties 'SamAccountName' -IncludeName = @(
# "ADM_*"
# "SADM_*"
# "PADM_*"
# "MADM_*"
# "NADM_*"
# "ADM0_*"
# "ADM1_*"
# "ADM2_*"
# )
# Configure rules for different types of users
$newPasswordConfigurationRuleSplat = @{
Name = 'Administrative Accounts'
Enable = $true
IncludeExpiring = $true
IncludePasswordNeverExpires = $true
PasswordNeverExpiresDays = 90
ReminderConfiguration = {
# follow expiration days of a user
New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfWeek Monday, Wednesday, Friday -ExpirationDays 60 -ComparisonType lt #-ExpirationDays @(-200..-1), 0, 1, 2, 3, 7, 15, 30, 60 -ComparisonType lt
#New-PasswordConfigurationRuleReminder -Type 'ManagerNotCompliant' -DayOfWeek Friday -ExpirationDays 300 -ComparisonType lt
#New-PasswordConfigurationRuleReminder -Type 'Security' -DayOfWeek Monday -ExpirationDays -1 -ComparisonType lt
}
ReminderDays = '-45', '-30', '-15', '-7', -195 #, 0, 1, 2, 3, 7, 15, 30, 60, 29, 28
IncludeOU = @(
"*OU=Accounts,OU=Administration,DC=ad,DC=evotec,DC=xyz"
"*OU=Administration,DC=ad,DC=evotec,DC=xyz"
)
ManagerReminder = $true
ProcessManagersOnly = $false
ManagerNotCompliant = $true
ManagerNotCompliantDisplayName = 'Global Service Desk'
ManagerNotCompliantEmailAddress = 'przemyslaw.klys@test.pl'
ManagerNotCompliantDisabled = $true
ManagerNotCompliantMissing = $true
ManagerNotCompliantMissingEmail = $true
ManagerNotCompliantLastLogonDays = 90
SecurityEscalation = $true
SecurityEscalationDisplayName = 'IT Security'
SecurityEscalationEmailAddress = 'przemyslaw.klys@test.pl'
#DisableDays = @(-171,-170,-172,-200)
#DisableType = 'in'
#DisableWhatIf = $true
}
New-PasswordConfigurationRule @newPasswordConfigurationRuleSplat
New-PasswordConfigurationRule -Name 'All others' -Enable -ReminderDays @(500..-500), 60, 59, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45, 600, -505 {
# follow expiration days of a user, you need to enable ManagerReminder for this functionality to work
New-PasswordConfigurationRuleReminder -Type 'Manager' -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60 -ComparisonType 'in'
# use a custom expiration days, and send only on specific days 1st, 10th and 15th of a month
#New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfMonth 1, 10, 15 -ExpirationDays -45, -30, -15, -7, 0, 1, 2, 3, 7, 15, 30, 60 -ComparisonType 'in'
# use a custom expiration days (only if it's less then 10 days left), and send only on specific days of a week
#New-PasswordConfigurationRuleReminder -Type 'Manager' -DayOfWeek Monday, Wednesday, Friday -ExpirationDays 10 -ComparisonType 'lt'
} -ExcludeOUFromOtherRules -IncludeExpiring -OverwriteEmailProperty 'extensionAttribute5' -OverwriteManagerProperty 'extensionAttribute1' -ManagerReminder #-DisableType 'in' -DisableDays @(-171,-200) -DisableWhatIf
# Template to user when sending email to user before password expires
New-PasswordConfigurationTemplate -Type PreExpiry -Template {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Dear ", "$DisplayName," -LineBreak
EmailText -Text "Your password will expire in $DaysToExpire days and if you do not change it, you will not be able to connect to the Evotec Network and IT services. "
EmailText -Text "Depending on your situation, please follow one of the methods below to change your password." -LineBreak
EmailText -Text "If you are connected to the Evotec Network (either directly or through VPN):"
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "Type in your old password and then type the new one according to the Policy (at least 8 characters, at least one uppercase letter, at least one lowercase letter, at least one number, at least one special character)"
EmailListItem -Text "After the change is complete you will be prompted with information that the password has been changed"
}
EmailText -Text "If you are not connected to the Evotec Network:"
EmailList {
EmailListItem -Text "Open [Password Change Link](https://account.activedirectory.windowsazure.com/ChangePassword.aspx) using your web browser"
EmailListItem -Text "Login using your current credentials"
EmailListItem -Text "On the change password form, type your old password and the new password that you want to set (twice)"
EmailListItem -Text "Click Submit"
}
EmailText -Text "Please also remember to modify your password on the email configuration of your Smartphone or Tablet." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject '[Password Expiring] Your password will expire on $DateExpiry ($DaysToExpire days)'
# Template to user when sending email to user after password expires
New-PasswordConfigurationTemplate -Type PostExpiry -Template {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Dear ", "$DisplayName," -LineBreak
EmailText -Text "Your password already expired on $PasswordLastSet. If you do not change it, you will not be able to connect to the Evotec Network and IT services. "
EmailText -Text "Depending on your situation, please follow one of the methods below to change your password." -LineBreak
EmailText -Text "If you are connected to the Evotec Network (either directly or through VPN):"
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "Type in your old password and then type the new one according to the Policy"
EmailListItem -Text "After the change is complete you will be prompted with information that the password has been changed"
}
EmailText -Text "If you are not connected to the Evotec Network:"
EmailList {
EmailListItem -Text "Open [Password Change Link](https://account.activedirectory.windowsazure.com/ChangePassword.aspx) using your web browser"
EmailListItem -Text "Login using your current credentials"
EmailListItem -Text "On the change password form, type your old password and the new password that you want to set (twice)"
EmailListItem -Text "Click Submit"
}
EmailText -Text "Please also remember to modify your password on the email configuration of your Smartphone or Tablet." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject '[Password Expiring] Your password expired on $DateExpiry ($DaysToExpire days ago)'
# Template to security team with all service accounts that have expired passwords and password never expires set to true
New-PasswordConfigurationTemplate -Type Security {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello ", "$ManagerDisplayName", "," -LineBreak -FontWeight normal, bold, normal
EmailText -Text "Below is a summary of ", "all service accounts", " where the passwords have exceeded the time limit stipulated in the password policy KGD. These accounts are all in violation of the KGD and immediate action/escalation should take place." -LineBreak -FontWeight normal, bold, normal
EmailText -Text "It has been agreed that the ", "password never expires", " flag has been set to ", "true", " to avoid business disruption/loss of service. As a result we require your escalation to the managers of the account to take immediate action to change the password ASAP." -LineBreak -FontWeight normal, bold, normal, bold, normal
EmailText -Text "Numerous automated reminders have been sent to the Manager, but no response/action has been taken yet." -LineBreak
EmailText -Text "Please reach out directly to the manager/site to ensure that these passwords are changed immediately." -LineBreak
EmailText -Text "If there is still lack of responses/action taken, it will be in your (IT Security) discretion to disable the account(s) question and take any appropriate action." -LineBreak -FontWeight bold
EmailTable -DataTable $ManagerUsersTable -HideFooter
EmailText -LineBreak
EmailText -Text "Many thanks in advance." -LineBreak
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject "[Passsword Expired] Following accounts are expired!"
# Template to manager with all accounts that have expired passwords
New-PasswordConfigurationTemplate -Type Manager {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Below is a summary of accounts where the password is due to expire soon. These accounts are either:"
EmailList {
EmailListItem -Text 'Managed by you'
EmailListItem -Text 'You are the manager of the owner of these accounts.'
}
EmailText -Text "Where you are the owner, please action the password change on each account outlined below, according to the rules specified by Password Policy." -LineBreak
EmailTable -DataTable $ManagerUsersTable -HideFooter
EmailText -LineBreak
EmailText -Text @(
"Please note that for Service Accounts, even though the ",
"'password never expires' "
"flag remains set to "
"'true' "
", the password MUST be changed before the expiry date specified in the above table. "
"It is the responsibility of the manager of the account to ensure that this takes place. "
) -FontWeight normal, bold, normal, bold, normal, normal -LineBreak
EmailText -Text @(
"Please make an effort "
"to change password yourself using known methods rather than asking the Service Desk to change the password for you. "
"If password is changed by Service Desk agent, there are at least 2 people knowing the password - Service Desk Agent and You! "
"Do you really want the Service Desk agent to know the password to critical system you manage/own? "
"Be responsible!"
) -FontWeight bold, normal, normal, normal, bold -LineBreak -Color None, None, None, None, Red
EmailText -Text "One of the ways to change the password is: " -FontWeight bold
EmailList {
EmailListItem -Text "Press CTRL+ALT+DEL"
EmailListItem -Text "Choose Change password"
EmailListItem -Text "In the account name - change it to the account you want to change password for." -FontWeight bold
EmailListItem -Text "Type in current password for the account and then type the new one according to the rules specified in the password policy."
EmailListItem -Text "After the change is complete you will be provided with information that the password has been changed"
}
EmailText -Text "Failure to take action could result in loss of service/escalation to the IT Security team." -LineBreak -FontWeight bold
EmailText -Text "Kind regards,"
EmailText -Text "IT Service Desk"
} -Subject "[Passsword Expiring] Accounts you manage/own are expiring or already expired"
# Template to Service Desk with information about manager missing, disabled, last logon >90 days, missing email for service accounts
New-PasswordConfigurationTemplate -Type ManagerNotCompliant {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Below is a summary of accounts where there is missing 'critical' information. These accounts are either:"
EmailList {
EmailListItem -Text "Missing a Manager in the AD - please add an active manager"
EmailListItem -Text "The Manager in AD is Disabled - please add an active manager"
EmailListItem -Text "Manager Last logon >90 days - please confirm if the manager is still an employee at Evotec/change the manager to an active manager"
EmailListItem -Text "Manager is missing email - add manager email"
}
EmailText -Text "Please contact the respective local IT Service Desk (outlined in the below table) to update this Manager's attributes in the AD directly. The suggested action to take can be found in the below table." -LineBreak
EmailTable -DataTable $ManagerUsersTableManagerNotCompliant -HideFooter
EmailText -LineBreak
EmailText -Text "Please note that all Service Accounts must have a Manager set in the AD, in order to fall within the Password Policy compliance notifications that are sent globally." -LineBreak
EmailText -Text "Kind regards," -LineBreak
EmailText -Text "IT Service Desk" -LineBreak
} -Subject "[Password Escalation] Accounts are expiring with non-compliant manager"
# Template to Admins with information summarizing what happened
New-PasswordConfigurationTemplate -Type Admin {
EmailImage -Source 'https://evotec.pl/wp-content/uploads/2015/05/Logo-evotec-012.png' -UrlLink '' -AlternativeText 'Evotec Logo' -Width '200' -Inline #-Height '100px'
EmailText -LineBreak
EmailText -Text "Hello $ManagerDisplayName," -LineBreak
EmailText -Text "Here's the summary of password notifications:"
EmailList {
EmailListItem -Text "Found users matching rule to send emails: ", $CountUserEmails
EmailListItem -Text "Sent emails to users: ", $CountUserEmailsSent
EmailListItem -Text "Couldn't send emails because of no email: ", $CountUserEmailsNotSentLackOfEmail
EmailListItem -Text "Couldn't send emails because other reasons: ", $CountUserEmailsNotSentOther
EmailListItem -Text "Sent emails to managers: ", $CountManagerEmails
EmailListItem -Text "Sent emails to security: ", $CountEscalationEmails
}
EmailText -Text "It took ", $TimeToProcess , " seconds to process the template." -LineBreak
EmailText -Text "Hope everything works correctly! ", " You can take a look at [Password Solution Report](https://adcompliance.Evotec.local/CustomReports/PasswordSolution_$(($Date).ToString('yyyy-MM-dd_HH_mm_ss')).html) for details." -LineBreak
EmailText -Text "Kind regards," -LineBreak
EmailText -Text "IT Service Desk" -LineBreak
} -Subject '[Password Summary] Passwords summary'
}
================================================
FILE: Examples/Example-ReRegisterTaskAsGMSA.ps1
================================================
$Tasks = Get-ScheduledTask -TaskPath "\" -TaskName "Automated-PasswordSolution"
# Fix all tasks to use proper account
foreach ($Task in $Tasks) {
schtasks /Change /TN $Task.TaskName /RU "GMSA$" /RP ""
}
foreach ($Task in $Tasks) {
#Start-ScheduledTask -TaskName $Task.TaskName -Verbose
}
================================================
FILE: Examples/Example-SearchNotification.ps1
================================================
Import-Module .\PasswordSolution.psd1 -Force
Find-PasswordNotification -SearchPath "$PSScriptRoot\Search\SearchLog_2022-08.xml" | Format-Table
#Find-PasswordNotification -SearchPath "$PSScriptRoot\Search\SearchLog_2021-06.xml" -Manager | Format-Table
================================================
FILE: Examples/WeakPasswordGenerator.ps1
================================================
$Months = @(
# english
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
# polish
"Styczen", "Luty", "Marzec", "Kwiecien", "Maj", "Czerwiec", "Lipiec", "Sierpien", "Wrzesien", "Pazdziernik", "Listopad", "Grudzien"
# spanish
'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'
# german
"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"
# russian
"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"
# french
'Janvier', 'Fevrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre'
) | Sort-Object -Unique
$Numbers = 0..9
$Years = 2020..2023
$SpecialChar = @("!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "-", "+", "=", "[", "]", "{", "}", "|", "\")
$Passwords = foreach ($Year in $Years) {
Write-Color -Text "Year: ", $Year -Color Yellow, White
$YearPasswords = foreach ($month in $months) {
foreach ($number in $numbers) {
foreach ($special in $SpecialChar) {
$month + $Year.ToString() + $number.ToString() + $special
$Year.ToString() + $month + $number.ToString() + $special
$month + $Year.ToString() + $special
}
}
}
Write-Color -Text "Year: ", $Year, " passwords created: ", $YearPasswords.Count -Color Yellow, White
$YearPasswords
}
$Passwords.Count
================================================
FILE: PasswordSolution.psd1
================================================
@{
AliasesToExport = @()
Author = 'Przemyslaw Klys'
CmdletsToExport = @()
CompanyName = 'Evotec'
CompatiblePSEditions = @('Desktop', 'Core')
Copyright = '(c) 2011 - 2025 Przemyslaw Klys @ Evotec. All rights reserved.'
Description = 'This module allows the creation of password expiry emails for users, managers, administrators, and security according to defined templates. It''s able to work with different rules allowing to fully customize who gets the email and when.'
FunctionsToExport = @('Find-Password', 'Find-PasswordEntra', 'Find-PasswordNotification', 'Find-PasswordQuality', 'New-PasswordConfigurationEmail', 'New-PasswordConfigurationEntra', 'New-PasswordConfigurationExternalUsers', 'New-PasswordConfigurationOption', 'New-PasswordConfigurationReplacement', 'New-PasswordConfigurationReport', 'New-PasswordConfigurationRule', 'New-PasswordConfigurationRuleReminder', 'New-PasswordConfigurationTemplate', 'New-PasswordConfigurationType', 'Show-PasswordQuality', 'Start-PasswordSolution')
GUID = 'c58ff818-1de6-4500-961c-a243c2043255'
ModuleVersion = '2.1.0'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
ExternalModuleDependencies = @('ActiveDirectory')
IconUri = 'https://evotec.xyz/wp-content/uploads/2022/08/PasswordSolution.png'
ProjectUri = 'https://github.com/EvotecIT/PasswordSolution'
Tags = @('password', 'passwordexpiry', 'activedirectory', 'windows')
}
}
RequiredModules = @(@{
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
ModuleName = 'PSSharedGoods'
ModuleVersion = '0.0.307'
}, @{
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
ModuleName = 'PSWriteHTML'
ModuleVersion = '1.28.0'
}, @{
Guid = '0b0ba5c5-ec85-4c2b-a718-874e55a8bc3f'
ModuleName = 'PSWriteColor'
ModuleVersion = '1.0.1'
}, @{
Guid = '2b0ea9f1-3ff1-4300-b939-106d5da608fa'
ModuleName = 'Mailozaurr'
ModuleVersion = '1.0.0'
}, 'ActiveDirectory')
RootModule = 'PasswordSolution.psm1'
}
================================================
FILE: PasswordSolution.psm1
================================================
#Get public and private function definition files.
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue -Recurse )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue -Recurse )
$Classes = @( Get-ChildItem -Path $PSScriptRoot\Classes\*.ps1 -ErrorAction SilentlyContinue -Recurse )
$Enums = @( Get-ChildItem -Path $PSScriptRoot\Enums\*.ps1 -ErrorAction SilentlyContinue -Recurse )
$AssemblyFolders = Get-ChildItem -Path $PSScriptRoot\Lib -Directory -ErrorAction SilentlyContinue
if ($AssemblyFolders.BaseName -contains 'Standard') {
$Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Standard\*.dll -ErrorAction SilentlyContinue )
} else {
if ($PSEdition -eq 'Core') {
$Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Core\*.dll -ErrorAction SilentlyContinue )
} else {
$Assembly = @( Get-ChildItem -Path $PSScriptRoot\Lib\Default\*.dll -ErrorAction SilentlyContinue )
}
}
$FoundErrors = @(
Foreach ($Import in @($Assembly)) {
try {
Add-Type -Path $Import.Fullname -ErrorAction Stop
} catch [System.Reflection.ReflectionTypeLoadException] {
Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
$LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
foreach ($E in $LoaderExceptions) {
Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
}
$true
#Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
} catch {
Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)"
$LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique
foreach ($E in $LoaderExceptions) {
Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)"
}
$true
#Write-Error -Message "StackTrace: $($_.Exception.StackTrace)"
}
}
#Dot source the files
Foreach ($Import in @($Private + $Public + $Classes + $Enums)) {
Try {
. $Import.Fullname
} Catch {
Write-Error -Message "Failed to import functions from $($import.Fullname): $_"
$true
}
}
)
if ($FoundErrors.Count -gt 0) {
$ModuleName = (Get-ChildItem $PSScriptRoot\*.psd1).BaseName
Write-Warning "Importing module $ModuleName failed. Fix errors before continuing."
break
}
Export-ModuleMember -Function '*' -Alias '*'
================================================
FILE: Private/Add-ManagerInformation.ps1
================================================
function Add-ManagerInformation {
[CmdletBinding()]
param(
[System.Collections.IDictionary] $SummaryDictionary,
[string] $Type,
[string] $ManagerType,
[Object] $Key,
[PSCustomObject] $User,
[PSCustomObject] $Rule,
[System.Collections.IDictionary] $Entra
)
if ($Key) {
if ($Entra.Enabled) {
# If entra is enabled we can use UserPrincipalName
$UserSearchString = $User.UserPrincipalName
if ($Key -is [string]) {
$KeyDN = $Key
} else {
$KeyDN = $Key.AdditionalProperties.displayName
}
} else {
$UserSearchString = $User.DistinguishedName
if ($Key -is [string]) {
$KeyDN = $Key
} else {
$KeyDN = $Key.DisplayName
}
}
if (-not $SummaryDictionary[$KeyDN]) {
$SummaryDictionary[$KeyDN] = [ordered] @{
Manager = $Key
ManagerDefault = [ordered] @{}
ManagerNotCompliant = [ordered] @{}
Security = [ordered] @{}
}
}
$SummaryDictionary[$KeyDN][$Type][$UserSearchString] = [ordered] @{
Manager = $User.ManagerDN
User = $User
Rule = $Rule
ManagerOption = $Type
Output = [ordered] @{}
}
$Default = [ordered] @{
DisplayName = $User.DisplayName
Enabled = $User.Enabled
SamAccountName = $User.SamAccountName
Domain = $User.Domain
DateExpiry = $User.DateExpiry
DaysToExpire = $User.DaysToExpire
PasswordLastSet = $User.PasswordLastSet
PasswordExpired = $User.PasswordExpired
}
if ($Type -ne 'ManagerDefault') {
$Extended = [ordered] @{
'Status' = $ManagerType
'Manager' = $User.Manager
'Manager Email' = $User.ManagerEmail
}
$SummaryDictionary[$KeyDN][$Type][$UserSearchString]['Output'] = [PSCustomObject] ( $Extended + $Default)
} else {
$SummaryDictionary[$KeyDN][$Type][$UserSearchString]['Output'] = [PSCustomObject] $Default
}
}
}
================================================
FILE: Private/Add-ParametersToString.ps1
================================================
function Add-ParametersToString {
<#
.SYNOPSIS
Short description
.DESCRIPTION
Long description
.PARAMETER String
Parameter description
.PARAMETER Parameter
Parameter description
.EXAMPLE
$Test = 'this is a string $Test - and $Test2 AND $tEST3'
Add-ParametersToString -String $Test -Parameter @{
Testooo = 'sdsds'
Test = 'oh my god'
Test2 = 'ole ole'
TEST3 = '56555'
}
.NOTES
General notes
#>
[CmdletBinding()]
param(
[string] $String,
[System.Collections.IDictionary] $Parameter
)
$Sorted = $Parameter.Keys | Sort-Object { $_.length } -Descending
foreach ($Key in $Sorted) {
$String = $String -ireplace [Regex]::Escape("`$$Key"), $Parameter[$Key]
}
$String
}
================================================
FILE: Private/Export-SearchInformation.ps1
================================================
function Export-SearchInformation {
[CmdletBinding()]
param(
[string] $SearchPath,
[System.Collections.IDictionary] $SummarySearch,
[string] $Today,
[Array] $SummaryUsersEmails,
[Array] $SummaryManagersEmails,
[Array] $SummaryEscalationEmails
)
if ($SearchPath) {
Write-Color -Text "[i]" , " Saving Search report " -Color White, Yellow, Green
if ($SummaryUsersEmails) {
$SummarySearch['EmailSent'][$Today] += $SummaryUsersEmails
}
if ($SummaryEscalationEmails) {
$SummarySearch['EmailEscalations'][$Today] += $SummaryEscalationEmails
}
if ($SummaryManagersEmails) {
$SummarySearch['EmailManagers'][$Today] += $SummaryManagersEmails
}
try {
$SummarySearch | Export-Clixml -LiteralPath $SearchPath -ErrorAction Stop
} catch {
Write-Color -Text "[e]", " Couldn't save to file $SearchPath", ". Error: ", $_.Exception.Message -Color White, Yellow, White, Yellow, White, Yellow, White
}
Write-Color -Text "[i]" , " Saving Search report ", "Done" -Color White, Yellow, Green
}
}
================================================
FILE: Private/Fromat-ReminderDays.ps1
================================================
function Format-ReminderDays {
<#
.SYNOPSIS
Formats an array of reminder days into a readable, concise format.
.DESCRIPTION
This function accepts an array of numbers (which may include nested arrays)
and always sorts them in ascending order. It then groups contiguous sequences
(where each subsequent number is either equal to or exactly 1 greater than the previous)
and formats groups of three or more unique numbers as a range. For clarity, if any
number in the range is negative the range is displayed using " to " (e.g. "-500 to 500")
to avoid confusion with hyphenated negatives.
.PARAMETER Days
An array of integers (or nested arrays of integers) representing reminder days.
.EXAMPLE
Format-ReminderDays -Days @(1,2,3,7,30)
# Returns: "1-3, 7, 30"
.EXAMPLE
$xxx = @(500..-500), 60, 59, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45, 600, -505
Format-ReminderDays -Days $xxx
# Returns: "-505, -500 to 500, 600"
.EXAMPLE
Format-ReminderDays -Days @(15..-500), 60, 59, 30, 15, 7, 3, 2, 1, 0, -7, -15, -30, -45, 600, -505
# Returns: -505, -500 to 15, 30, 59, 60, 600
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[Array]$Days
)
# Flatten the input array (to handle nested arrays like those produced by ranges)
$flatDays = @()
foreach ($item in $Days) {
if ($item -is [Array]) {
$flatDays += $item
} else {
$flatDays += $item
}
}
# Convert all items to integers.
$flatDays = $flatDays | ForEach-Object { [int]$_ }
# Always sort in ascending order.
$sortedDays = $flatDays | Sort-Object
# Group contiguous numbers.
$groups = @()
$currentGroup = @($sortedDays[0])
for ($i = 1; $i -lt $sortedDays.Count; $i++) {
$current = $sortedDays[$i]
$previous = $sortedDays[$i - 1]
# Group if the current number is equal (duplicate) or exactly 1 greater than the previous.
if ($current -eq $previous -or $current -eq $previous + 1) {
$currentGroup += $current
} else {
$groups += , @($currentGroup)
$currentGroup = @($current)
}
}
$groups += , @($currentGroup)
# Format each group into a string.
$formattedGroups = foreach ($group in $groups) {
# Count unique numbers in the group.
$uniqueCount = ($group | Select-Object -Unique).Count
if ($uniqueCount -ge 3) {
# Use " to " when any value is negative (for clarity)
if ($group[0] -lt 0 -or $group[-1] -lt 0) {
"$($group[0]) to $($group[-1])"
} else {
"$($group[0])-$($group[-1])"
}
} else {
# For groups with fewer than 3 unique numbers, list the numbers separated by commas.
$group -join ", "
}
}
return ($formattedGroups -join ", ")
}
================================================
FILE: Private/Import-SearchInformation.ps1
================================================
function Import-SearchInformation {
[CmdletBinding()]
param(
[string] $SearchPath
)
if ($SearchPath) {
if (Test-Path -LiteralPath $SearchPath) {
try {
Write-Color -Text "[i]", " Loading file ", $SearchPath -Color White, Yellow, White, Yellow, White, Yellow, White
$SummarySearch = Import-Clixml -LiteralPath $SearchPath -ErrorAction Stop
} catch {
Write-Color -Text "[e]", " Couldn't load the file $SearchPath", ". Skipping...", $_.Exception.Message -Color White, Yellow, White, Yellow, White, Yellow, White
}
}
}
if (-not $SummarySearch) {
$SummarySearch = [ordered] @{
EmailSent = [ordered] @{}
EmailManagers = [ordered] @{}
EmailEscalations = [ordered] @{}
}
}
$SummarySearch
}
================================================
FILE: Private/Invoke-PasswordRuleProcessing.ps1
================================================
function Invoke-PasswordRuleProcessing {
[CmdletBinding()]
param(
[System.Collections.IDictionary] $Rule,
[System.Collections.IDictionary] $Summary,
[System.Collections.IDictionary] $CachedUsers,
[System.Collections.IDictionary] $AllSkipped,
[System.Collections.IDictionary] $Locations,
[System.Collections.IDictionary] $Logging,
[System.Collections.IDictionary] $UsersExternalSystem,
[DateTime] $TodayDate,
[System.Collections.IDictionary] $Entra
)
# Go for each rule and check if the user is in any of those rules
if ($Rule.Enable -eq $true) {
Write-Color -Text "[i]", " Processing rule ", $Rule.Name, ' status: ', $Rule.Enable -Color Yellow, White, Green, White, Green, White, Green, White
# Lets create summary for the rule
if (-not $Summary['Rules'][$Rule.Name] ) {
$Summary['Rules'][$Rule.Name] = [ordered] @{}
}
# this will make sure to expand array of multiple arrays of ints if provided
# for example: (-150..-100),(-60..0), 1, 2, 3
if ($null -ne $Rule.Reminders) {
$Rule.Reminders = $Rule.Reminders | ForEach-Object { $_ }
}
# Do the same for DisableDays, if provided
if ($null -ne $Rule.DisableDays) {
$Rule.DisableDays = $Rule.DisableDays | ForEach-Object { $_ }
}
foreach ($User in $CachedUsers.Values) {
if ($Entra.Enabled) {
$UserSearchString = $User.UserPrincipalName
} else {
$UserSearchString = $User.DistinguishedName
}
if ($User.Enabled -eq $false) {
# We don't want to have disabled users
continue
}
if ($Rule.ExcludeOUFromOtherRules) {
# Rule defined that user within OU's already used in processed Rules are excluded
$FoundOU = $false
foreach ($OU in $Summary.Tracking.IncludeOU) {
if ($User.OrganizationalUnit -like $OU) {
$FoundOU = $true
break
}
}
# if OU is found we need to exclude the user
if ($FoundOU) {
continue
}
}
if ($Rule.ExcludeOU.Count -gt 0) {
# Rule defined that user within specific OU has to be excluded
$FoundOU = $false
foreach ($OU in $Rule.ExcludeOU) {
# Lets update global tracking
if ($Summary['Tracking']['ExcludeOU'] -notcontains $OU) {
$Summary['Tracking']['ExcludeOU'].Add($OU)
}
if ($User.OrganizationalUnit -like $OU) {
$FoundOU = $true
break
}
}
# if OU is found we need to exclude the user
if ($FoundOU) {
continue
}
}
if ($Rule.IncludeOU.Count -gt 0) {
# Rule defined that only user within specific OU has to be found
$FoundOU = $false
foreach ($OU in $Rule.IncludeOU) {
# Lets update global tracking
if ($Summary['Tracking']['IncludeOU'] -notcontains $OU) {
$Summary['Tracking']['IncludeOU'].Add($OU)
}
if ($User.OrganizationalUnit -like $OU) {
$FoundOU = $true
break
}
}
if (-not $FoundOU) {
continue
}
}
if ($Rule.ExcludeGroup.Count -gt 0) {
# Rule defined that only user within specific group has to be found
$FoundGroup = $false
foreach ($Group in $Rule.ExcludeGroup) {
if ($User.MemberOf -contains $Group) {
$FoundGroup = $true
break
}
}
# If found, we need to skip user
if ($FoundGroup) {
continue
}
}
if ($Rule.IncludeGroup.Count -gt 0) {
# Rule defined that only user within specific group has to be found
$FoundGroup = $false
foreach ($Group in $Rule.IncludeGroup) {
if ($User.MemberOf -contains $Group) {
$FoundGroup = $true
break
}
}
if (-not $FoundGroup) {
continue
}
}
if ($Rule.IncludeName.Count -gt 0) {
$IncludeName = $false
foreach ($Name in $Rule.IncludeName) {
foreach ($Property in $Rule.IncludeNameProperties) {
if ($User.$Property -like $Name) {
$IncludeName = $true
break
}
}
if ($IncludeName) {
break
}
}
if (-not $IncludeName) {
continue
}
}
if ($Rule.ExcludeName.Count -gt 0) {
$ExcludeName = $false
foreach ($Name in $Rule.ExcludeName) {
foreach ($Property in $Rule.ExcludeNameProperties) {
if ($User.$Property -like $Name) {
$ExcludeName = $true
break
}
}
if ($ExcludeName) {
break
}
}
if ($ExcludeName) {
continue
}
}
if ($Summary['Notify'][$UserSearchString] -and $Summary['Notify'][$UserSearchString].ProcessManagersOnly -ne $true) {
# User already exists in the notifications - rules are overlapping, we only take the first one
# We also check for ProcessManagersOnly because we don't want first rule to ignore any other rules for users
continue
}
if ($Rule.IncludePasswordNeverExpires -and $Rule.IncludeExpiring) {
if ($User.PasswordNeverExpires -eq $true) {
$DaysToPasswordExpiry = $Rule.PasswordNeverExpiresDays - $User.PasswordDays
$User.DaysToExpire = $DaysToPasswordExpiry
}
} elseif ($Rule.IncludeExpiring) {
if ($User.PasswordNeverExpires -eq $true) {
# we skip those that never expire
continue
}
} elseif ($Rule.IncludePasswordNeverExpires) {
if ($User.PasswordNeverExpires -eq $true) {
$DaysToPasswordExpiry = $Rule.PasswordNeverExpiresDays - $User.PasswordDays
$User.DaysToExpire = $DaysToPasswordExpiry
} else {
# we skip users who expire
continue
}
} else {
Write-Color -Text "[i]", " Processing rule ", $Rule.Name, " doesn't include IncludePasswordNeverExpires nor IncludeExpiring so skipping." -Color Yellow, White, Green, White, Green, White, Green, White
continue
}
if ($null -eq $User.DaysToExpire) {
# This is to track users that our account may not have permissions over
if ($Logging.NotifyOnUserDaysToExpireNull) {
Write-Color -Text @(
"[i]",
" User ",
$User.DisplayName,
" (",
$User.UserPrincipalName,
")",
" days to expire not set. ",
"(",
"Password Last Set: ",
$User.PasswordLastSet,
")",
" (Password at next logon: ",
$User.PasswordAtNextLogon, ")"
) -Color Yellow, White, Yellow, White, Yellow, White, White, White, Yellow, DarkCyan, White, Yellow, DarkCyan, White
}
# if days to expire is not set, password last set is not set either
# this means account either was never used or account we're using to has no permissions over that account
$AllSkipped[$UserSearchString] = $User
$Location = $User.OrganizationalUnit
if (-not $Location) {
$Location = 'Default'
}
if (-not $Locations[$Location]) {
$Locations[$Location] = [PSCustomObject] @{
Location = $Location
Count = 0
CountExpired = 0
Names = [System.Collections.Generic.List[string]]::new()
NamesExpired = [System.Collections.Generic.List[string]]::new()
}
}
if ($User.PasswordExpired) {
$Locations[$Location].CountExpired++
$Locations[$Location].NamesExpired.Add($User.SamAccountName)
} else {
$Locations[$Location].Count++
$Locations[$Location].Names.Add($User.SamAccountName)
}
}
# Lets find users that expire, and match our rule
if ($null -ne $User.DaysToExpire -and $User.DaysToExpire -in $Rule.Reminders) {
# check if we need to notify user or just manager
if (-not $Rule.ProcessManagersOnly) {
if ($Logging.NotifyOnUserMatchingRule) {
Write-Color -Text "[i]", " User ", $User.DisplayName, " (", $User.UserPrincipalName, ")", " days to expire: ", $User.DaysToExpire, " " -Color Yellow, White, Yellow, White, Yellow, White, White, Blue
}
# This is required for email notification to different email address
# User wanted to use different email address for notifications based on external property such as
# employeeID, employeeNumber, extensionAttributes, etc.
# normally this wouldn't be required if it's global setting, but if only a handful of users need to have their address changed
# the per rule overwriteemailproperty should be used
if ($Rule.OverwriteEmailProperty) {
$NewPropertyWithEmail = $Rule.OverwriteEmailProperty
if ($NewPropertyWithEmail -and $User.$NewPropertyWithEmail) {
$User.EmailAddress = $User.$NewPropertyWithEmail
}
}
if ($Rule.OverwriteEmailFromExternalUsers) {
$ExternalUser = $null
$ADProperty = $UsersExternalSystem.ActiveDirectoryProperty
$EmailProperty = $UsersExternalSystem.EmailProperty
$ExternalUser = $UsersExternalSystem['Users'][$User.$ADProperty]
if ($ExternalUser -and $ExternalUser.$EmailProperty -like '*@*') {
$User.EmailAddress = $ExternalUser.$EmailProperty
}
}
$Summary['Notify'][$UserSearchString] = [ordered] @{
User = $User
Rule = $Rule
ProcessManagersOnly = $Rule.ProcessManagersOnly
}
# If we need to send an email to manager we need to update rules, just in case the user has not matched for user section
if ($Summary['Rules'][$Rule.Name][$UserSearchString]) {
# User exists, update reason
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleOptions.Add('User')
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleName = $Rule.Name
} else {
# User doesn't exists in rules, add it
$Summary['Rules'][$Rule.Name][$UserSearchString] = [ordered] @{
User = $User
Rule = $Rule
ProcessManagersOnly = $Rule.ProcessManagersOnly
}
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleOptions.Add('User')
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleName = $Rule.Name
}
}
}
# this is to overwrite manager by using extensionAttribute or any other field in AD
# it works on SamAccountName, DistinguishedName only
if ($Rule.OverwriteManagerProperty) {
$NewPropertyWithManager = $Rule.OverwriteManagerProperty
if ($NewPropertyWithManager -and $User.$NewPropertyWithManager) {
$NewManager = $CachedUsers[$User.$NewPropertyWithManager]
if ($NewManager -and $NewManager.Mail -like "*@*") {
$User.ManagerEmail = $NewManager.Mail
$User.Manager = $NewManager.DisplayName
$User.ManagerSamAccountName = $NewManager.SamAccountName
$User.ManagerEnabled = $NewManager.Enabled
$User.ManagerLastLogon = $NewManager.LastLogonDate
if ($User.ManagerLastLogon) {
$User.ManagerLastLogonDays = $( - $($User.ManagerLastLogon - $Today).Days)
} else {
$User.ManagerLastLogonDays = $null
}
$User.ManagerType = $NewManager.ObjectClass
$User.ManagerDN = $NewManager.DistinguishedName
}
}
}
# Lets find users that we need to notify manager about
if ($null -ne $User.DaysToExpire -and $Rule.SendToManager) {
if ($Rule.SendToManager.Manager -and $Rule.SendToManager.Manager.Enable -eq $true -and $User.ManagerStatus -eq 'Enabled' -and $User.ManagerEmail -like "*@*") {
$SendToManager = $true
# Manager is enabled and has an email, this is standard situation for manager in AD
# But before we go and do that, maybe user wants to send emails to managers if those users are in specific group or OU
if ($Rule.SendToManager.Manager.IncludeOU.Count -gt 0) {
# Rule defined that only user withi specific OU has to be found
$FoundOU = $false
foreach ($OU in $Rule.SendToManager.Manager.IncludeOU) {
if ($User.OrganizationalUnit -like $OU) {
$FoundOU = $true
break
}
}
if (-not $FoundOU) {
$SendToManager = $false
}
}
if ($SendToManager -and $Rule.SendToManager.Manager.ExcludeOU.Count -gt 0) {
$FoundOU = $false
foreach ($OU in $Rule.SendToManager.Manager.ExcludeOU) {
if ($User.OrganizationalUnit -like $OU) {
$FoundOU = $true
break
}
}
# if OU is found we need to exclude the user
if ($FoundOU) {
$SendToManager = $false
}
}
if ($SendToManager -and $Rule.SendToManager.Manager.ExcludeGroup.Count -gt 0) {
# Rule defined that only user withi specific group has to be found
$FoundGroup = $false
foreach ($Group in $Rule.SendToManager.Manager.ExcludeGroup) {
if ($User.MemberOf -contains $Group) {
$FoundGroup = $true
break
}
}
# if Group found, we need to skip this user
if ($FoundGroup) {
$SendToManager = $false
}
}
if ($SendToManager -and $Rule.SendToManager.Manager.IncludeGroup.Count -gt 0) {
# Rule defined that only user within specific group has to be found
$FoundGroup = $false
foreach ($Group in $Rule.SendToManager.Manager.IncludeGroup) {
if ($User.MemberOf -contains $Group) {
$FoundGroup = $true
break
}
}
if (-not $FoundGroup) {
$SendToManager = $false
}
}
if ($SendToManager) {
$SendToManager = $false
if ($Rule.SendToManager.Manager.Reminders.Default.Enable -eq $true -and $null -eq $Rule.SendToManager.Manager.Reminders.Default.Reminder -and $User.DaysToExpire -in $Rule.Reminders) {
# Use default reminder as per user, not per manager
$SendToManager = $true
} elseif ($Rule.SendToManager.Manager.Reminders.Default.Enable -eq $true -and $Rule.SendToManager.Manager.Reminders.Default.Reminder -and $User.DaysToExpire -in $Rule.SendToManager.Manager.Reminders.Default.Reminder) {
# User manager reminder as per manager config
$SendToManager = $true
}
if (-not $SendToManager -and $Rule.SendToManager.Manager.Reminders.OnDay -and $Rule.SendToManager.Manager.Reminders.OnDay.Enable -eq $true) {
foreach ($Day in $Rule.SendToManager.Manager.Reminders.OnDay.Days) {
if ($Day -eq "$($TodayDate.DayOfWeek)") {
if ($Rule.SendToManager.Manager.Reminders.OnDay.ComparisonType -eq 'lt') {
if ($User.DaysToExpire -lt $Rule.SendToManager.Manager.Reminders.OnDay.Reminder) {
$SendToManager = $true
break
}
} elseif ($Rule.SendToManager.Manager.Reminders.OnDay.ComparisonType -eq 'gt') {
if ($User.DaysToExpire -gt $Rule.SendToManager.Manager.Reminders.OnDay.Reminder) {
$SendToManager = $true
break
}
} elseif ($Rule.SendToManager.Manager.Reminders.OnDay.ComparisonType -eq 'eq') {
if ($User.DaysToExpire -eq $Rule.SendToManager.Manager.Reminders.OnDay.Reminder) {
$SendToManager = $true
break
}
} elseif ($Rule.SendtoManager.Manager.Reminders.OnDay.ComparisonType -eq 'in') {
if ($User.DaysToExpire -in $Rule.SendToManager.Manager.Reminders.OnDay.Reminder) {
$SendToManager = $true
break
}
}
}
}
}
if (-not $SendToManager -and $Rule.SendToManager.Manager.Reminders.OnDayOfMonth -and $Rule.SendToManager.Manager.Reminders.OnDayOfMonth.Enable -eq $true) {
foreach ($Day in $Rule.SendToManager.Manager.Reminders.OnDayOfMonth.Days) {
if ($Day -eq $TodayDate.Day) {
if ($Rule.SendToManager.Manager.Reminders.OnDayOfMonth.ComparisonType -eq 'lt') {
if ($User.DaysToExpire -lt $Rule.SendToManager.Manager.Reminders.OnDayOfMonth.Reminder) {
$SendToManager = $true
break
}
} elseif ($Rule.SendToManager.Manager.Reminders.OnDayOfMonth.ComparisonType -eq 'gt') {
if ($User.DaysToExpire -gt $Rule.SendToManager.Manager.Reminders.OnDayOfMonth.Reminder) {
$SendToManager = $true
break
}
} elseif ($Rule.SendToManager.Manager.Reminders.OnDayOfMonth.ComparisonType -eq 'eq') {
if ($User.DaysToExpire -eq $Rule.SendToManager.Manager.Reminders.OnDayOfMonth.Reminder) {
$SendToManager = $true
break
}
} elseif ($Rule.SendtoManager.Manager.Reminders.OnDayOfMonth.ComparisonType -eq 'in') {
if ($User.DaysToExpire -in $Rule.SendToManager.Manager.Reminders.OnDayOfMonth.Reminder) {
$SendToManager = $true
break
}
}
}
}
}
if ($SendToManager) {
if ($Logging.NotifyOnUserMatchingRuleForManager) {
Write-Color -Text "[i]", " User (manager rule) ", $User.DisplayName, " (", $User.UserPrincipalName, ")", " days to expire: ", $User.DaysToExpire, " " -Color Yellow, White, Yellow, White, Yellow, White, White, Blue
}
# If we need to send an email to manager we need to update rules, just in case the user has not matched for user section
if ($Summary['Rules'][$Rule.Name][$UserSearchString]) {
# User exists, update reason
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleOptions.Add('Manager')
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleName = $Rule.Name
} else {
# User doesn't exists in rules, add it
$Summary['Rules'][$Rule.Name][$UserSearchString] = [ordered] @{
User = $User
Rule = $Rule
ProcessManagersOnly = $Rule.ProcessManagersOnly
}
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleOptions.Add('Manager')
$Summary['Rules'][$Rule.Name][$UserSearchString].User.RuleName = $Rule.Name
}
# Push manager to list
$Splat = [ordered] @{
SummaryDictionary = $Summary['NotifyManager']
Type = 'ManagerDefault'
ManagerType = 'Ok'
Key = $User.ManagerDN
User = $User
Rule = $Rule
Entra = $Entra
}
Add-ManagerInformation @Splat
}
}
} else {
if ($Rule.SendToManager.Manager -and $Rule.SendToManager.Manager.Enable -eq $true) {
# Manager rule is enabled but manager is not enabled or has no email
if ($Logging.NotifyOnUserMatchingRuleForManagerButNotCompliant) {
Write-Color -Text "[i]", " User (manager rule) ", $User.DisplayName, " (", $User.UserPrincipalName, ")", " days to expire: ", $User.DaysToExpire, ", manager status: ", $User.ManagerStatus, ". Reason to skip: ", "No manager or manager is not enabled or manager has no email " -Color Yellow, White, Yellow, White, Yellow, White, White, Red, White, Red, White, Red
}
}
}
}
# Lets find users that have no manager, manager is not enabled or manager has no email
if ($Rule.SendToManager -and $Rule.SendToManager.ManagerNotCompliant -and $Rule.SendToManager.ManagerNotCompliant.Enable -eq $true -and $Rule.SendToManager.ManagerNotCompliant.Manager) {
# Not compliant (missing, disabled, no email), covers all the below options
if ($Rule.SendToManager.ManagerNotCompliant -and $Rule.SendToManager.ManagerNotCompliant.Enable -and $Rule.SendToManager.ManagerNotCompliant.Manager) {
$ManagerNotCompliant = $true
# But before we go and do that, maybe user wants to send emails to managers only if those users are in specific group or OU
if ($Rule.SendToManager.ManagerNotCompliant.IncludeOU.Count -gt 0) {
# Rule defined that only user withi specific OU has to be found
$FoundOU = $false
foreach ($OU in $Rule.SendToManager.ManagerNotCompliant.IncludeOU) {
if ($User.OrganizationalUnit -like $OU) {
$FoundOU = $true
break
}
}
gitextract_pdir1fnf/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── Build/ │ └── Manage-Module.ps1 ├── CHANGELOG.MD ├── Docs/ │ ├── Find-Password.md │ ├── Find-PasswordNotification.md │ ├── Find-PasswordQuality.md │ ├── New-PasswordConfigurationEmail.md │ ├── New-PasswordConfigurationOption.md │ ├── New-PasswordConfigurationReport.md │ ├── New-PasswordConfigurationRule.md │ ├── New-PasswordConfigurationRuleReminder.md │ ├── New-PasswordConfigurationTemplate.md │ ├── New-PasswordConfigurationType.md │ ├── Readme.md │ ├── Show-PasswordQuality.md │ └── Start-PasswordSolution.md ├── Examples/ │ ├── Example-EncryptPassword.ps1 │ ├── Example-FindUsers.ps1 │ ├── Example-FindUsersAdvanced.ps1 │ ├── Example-FindUsersEntra.ps1 │ ├── Example-FindUsersPasswordQualityConsole.ps1 │ ├── Example-FindUsersPasswordQualityConsoleWithReplacements.ps1 │ ├── Example-FindUsersPasswordQualityReport.ps1 │ ├── Example-FindUsersPasswordQualityReportWithReplacements.ps1 │ ├── Example-PasswordDashboard.ps1 │ ├── Example-PasswordSolution-Entra.ps1 │ ├── Example-PasswordSolution-LegacyConfiguration01.ps1 │ ├── Example-PasswordSolution-ModernConfiguration01.ps1 │ ├── Example-ReRegisterTaskAsGMSA.ps1 │ ├── Example-SearchNotification.ps1 │ └── WeakPasswordGenerator.ps1 ├── PasswordSolution.psd1 ├── PasswordSolution.psm1 ├── Private/ │ ├── Add-ManagerInformation.ps1 │ ├── Add-ParametersToString.ps1 │ ├── Export-SearchInformation.ps1 │ ├── Fromat-ReminderDays.ps1 │ ├── Import-SearchInformation.ps1 │ ├── Invoke-PasswordRuleProcessing.ps1 │ ├── New-HTMLReport.ps1 │ ├── Send-PasswordAdminNotifications.ps1 │ ├── Send-PasswordEmail.ps1 │ ├── Send-PasswordManagerNotifications.ps1 │ ├── Send-PasswordSecurityNotifications.ps1 │ ├── Send-PasswordUserNotifications.ps1 │ └── Set-PasswordConfiguration.ps1 ├── Public/ │ ├── Find-Password.ps1 │ ├── Find-PasswordEntra.ps1 │ ├── Find-PasswordNotification.ps1 │ ├── Find-PasswordQuality.ps1 │ ├── New-PasswordConfigurationEmail.ps1 │ ├── New-PasswordConfigurationEntra.ps1 │ ├── New-PasswordConfigurationExternalUsers.ps1 │ ├── New-PasswordConfigurationOption.ps1 │ ├── New-PasswordConfigurationReplacement.ps1 │ ├── New-PasswordConfigurationReport.ps1 │ ├── New-PasswordConfigurationRule.ps1 │ ├── New-PasswordConfigurationRuleReminder.ps1 │ ├── New-PasswordConfigurationTemplate.ps1 │ ├── New-PasswordConfigurationType.ps1 │ ├── Show-PasswordQuality.ps1 │ └── Start-PasswordSolution.ps1 └── README.MD
Condensed preview — 64 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (538K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 64,
"preview": "github: PrzemyslawKlys\ncustom: https://paypal.me/PrzemyslawKlys"
},
{
"path": ".gitignore",
"chars": 55,
"preview": "Ignore/*\n.vs/*\n.vscode/*\n*.html\n*.log\n*.xml\nArtefacts/*"
},
{
"path": "Build/Manage-Module.ps1",
"chars": 6052,
"preview": "Clear-Host\nImport-Module \"PSPublishModule\" -Force\n\nInvoke-ModuleBuild -ModuleName 'PasswordSolution' {\n # Usual defau"
},
{
"path": "CHANGELOG.MD",
"chars": 8749,
"preview": "# PasswordSolution Release History\n\n## 2.0.3\n- Fix formatting in HTML output\n- Fix deletion of log files/reports to spe"
},
{
"path": "Docs/Find-Password.md",
"chars": 2968,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# Fin"
},
{
"path": "Docs/Find-PasswordNotification.md",
"chars": 1505,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# Fin"
},
{
"path": "Docs/Find-PasswordQuality.md",
"chars": 2561,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# Fin"
},
{
"path": "Docs/New-PasswordConfigurationEmail.md",
"chars": 10274,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/New-PasswordConfigurationOption.md",
"chars": 4905,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/New-PasswordConfigurationReport.md",
"chars": 5969,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/New-PasswordConfigurationRule.md",
"chars": 9126,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/New-PasswordConfigurationRuleReminder.md",
"chars": 2607,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/New-PasswordConfigurationTemplate.md",
"chars": 1652,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/New-PasswordConfigurationType.md",
"chars": 2118,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# New"
},
{
"path": "Docs/Readme.md",
"chars": 1715,
"preview": "---\nModule Name: PasswordSolution\nModule Guid: c58ff818-1de6-4500-961c-a243c2043255\nDownload Help Link: {{ Update Downlo"
},
{
"path": "Docs/Show-PasswordQuality.md",
"chars": 4710,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# Sho"
},
{
"path": "Docs/Start-PasswordSolution.md",
"chars": 7267,
"preview": "---\nexternal help file: PasswordSolution-help.xml\nModule Name: PasswordSolution\nonline version:\nschema: 2.0.0\n---\n\n# Sta"
},
{
"path": "Examples/Example-EncryptPassword.ps1",
"chars": 106,
"preview": "(Get-Credential -UserName 'test' -Message 'Password').Password | ConvertFrom-SecureString | Set-Clipboard"
},
{
"path": "Examples/Example-FindUsers.ps1",
"chars": 569,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$Users = Find-Password -OverwriteEmailProperty 'extensionAttribute7' -Ove"
},
{
"path": "Examples/Example-FindUsersAdvanced.ps1",
"chars": 580,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$RuleProperties = @(\n 'ExtensionAttribute7'\n 'extensionAttribute7'\n"
},
{
"path": "Examples/Example-FindUsersEntra.ps1",
"chars": 793,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\nConnect-MgGraph -Scopes \"User.Read.All\" -NoWelcome\n\n$Users = Find-Passwor"
},
{
"path": "Examples/Example-FindUsersPasswordQualityConsole.ps1",
"chars": 184,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$Users = Find-PasswordQuality\n$Users | Format-Table\n\n#$Users = Find-Passw"
},
{
"path": "Examples/Example-FindUsersPasswordQualityConsoleWithReplacements.ps1",
"chars": 452,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$Replacements = @(\n New-PasswordConfigurationReplacement -PropertyName"
},
{
"path": "Examples/Example-FindUsersPasswordQualityReport.ps1",
"chars": 1144,
"preview": "Clear-Host\nImport-Module .\\PasswordSolution.psd1 -Force\n\n# option 1, one-liner\n# Show-PasswordQuality -FilePath C:\\Temp"
},
{
"path": "Examples/Example-FindUsersPasswordQualityReportWithReplacements.ps1",
"chars": 1041,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$showPasswordQualitySplat = @{\n FilePath = \"$PSScriptRo"
},
{
"path": "Examples/Example-PasswordDashboard.ps1",
"chars": 239,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$Passwords = Find-Password\n\nNew-HTML {\n New-TableOption -DataStore Jav"
},
{
"path": "Examples/Example-PasswordSolution-Entra.ps1",
"chars": 20826,
"preview": "Clear-Host\nImport-Module .\\PasswordSolution.psd1 -Force\n\n$Date = Get-Date\n\nConnect-MgGraph -Scopes \"User.Read.All\" -NoW"
},
{
"path": "Examples/Example-PasswordSolution-LegacyConfiguration01.ps1",
"chars": 32154,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\n$Date = Get-Date\n\n$GraphCredentials = @{\n ClientID = '0fb383f1-8bf"
},
{
"path": "Examples/Example-PasswordSolution-ModernConfiguration01.ps1",
"chars": 21178,
"preview": "Clear-Host\nImport-Module .\\PasswordSolution.psd1 -Force\n\n$Date = Get-Date\n\nStart-PasswordSolution {\n $Options = @{\n "
},
{
"path": "Examples/Example-ReRegisterTaskAsGMSA.ps1",
"chars": 297,
"preview": "$Tasks = Get-ScheduledTask -TaskPath \"\\\" -TaskName \"Automated-PasswordSolution\"\n\n# Fix all tasks to use proper account\n"
},
{
"path": "Examples/Example-SearchNotification.ps1",
"chars": 252,
"preview": "Import-Module .\\PasswordSolution.psd1 -Force\n\nFind-PasswordNotification -SearchPath \"$PSScriptRoot\\Search\\SearchLog_202"
},
{
"path": "Examples/WeakPasswordGenerator.ps1",
"chars": 1653,
"preview": "$Months = @(\n # english\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \""
},
{
"path": "PasswordSolution.psd1",
"chars": 2392,
"preview": "@{\n AliasesToExport = @()\n Author = 'Przemyslaw Klys'\n CmdletsToExport = @()\n Compa"
},
{
"path": "PasswordSolution.psm1",
"chars": 2595,
"preview": "#Get public and private function definition files.\n$Public = @( Get-ChildItem -Path $PSScriptRoot\\Public\\*.ps1 -ErrorAc"
},
{
"path": "Private/Add-ManagerInformation.ps1",
"chars": 2404,
"preview": "function Add-ManagerInformation {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] $SummaryDic"
},
{
"path": "Private/Add-ParametersToString.ps1",
"chars": 822,
"preview": "function Add-ParametersToString {\n <#\n .SYNOPSIS\n Short description\n\n .DESCRIPTION\n Long description\n\n "
},
{
"path": "Private/Export-SearchInformation.ps1",
"chars": 1189,
"preview": "function Export-SearchInformation {\n [CmdletBinding()]\n param(\n [string] $SearchPath,\n [System.Coll"
},
{
"path": "Private/Fromat-ReminderDays.ps1",
"chars": 2961,
"preview": "function Format-ReminderDays {\n <#\n .SYNOPSIS\n Formats an array of reminder days into a readable, concise form"
},
{
"path": "Private/Import-SearchInformation.ps1",
"chars": 884,
"preview": "function Import-SearchInformation {\n [CmdletBinding()]\n param(\n [string] $SearchPath\n )\n if ($Search"
},
{
"path": "Private/Invoke-PasswordRuleProcessing.ps1",
"chars": 51101,
"preview": "function Invoke-PasswordRuleProcessing {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] $Rul"
},
{
"path": "Private/New-HTMLReport.ps1",
"chars": 52984,
"preview": "function New-HTMLReport {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] $Report,\n [S"
},
{
"path": "Private/Send-PasswordAdminNotifications.ps1",
"chars": 3390,
"preview": "function Send-PasswordAdminNotifications {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] $A"
},
{
"path": "Private/Send-PasswordEmail.ps1",
"chars": 7780,
"preview": "function Send-PasswordEmail {\n [CmdletBinding()]\n param(\n [scriptblock] $Template,\n [PSCustomObject"
},
{
"path": "Private/Send-PasswordManagerNotifications.ps1",
"chars": 12811,
"preview": "function Send-PasswordManagerNofifications {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] "
},
{
"path": "Private/Send-PasswordSecurityNotifications.ps1",
"chars": 6312,
"preview": "function Send-PasswordSecurityNotifications {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary]"
},
{
"path": "Private/Send-PasswordUserNotifications.ps1",
"chars": 10250,
"preview": "function Send-PasswordUserNofifications {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] $Us"
},
{
"path": "Private/Set-PasswordConfiguration.ps1",
"chars": 21221,
"preview": "function Set-PasswordConfiguration {\n [CmdletBinding()]\n param(\n [System.Collections.IDictionary] $Logging"
},
{
"path": "Public/Find-Password.ps1",
"chars": 39888,
"preview": "function Find-Password {\n <#\n .SYNOPSIS\n Scan Active Directory forest for all users and their password expirat"
},
{
"path": "Public/Find-PasswordEntra.ps1",
"chars": 19638,
"preview": "function Find-PasswordEntra {\n [CmdletBinding()]\n param(\n [Parameter(DontShow)][string] $HashtableField = "
},
{
"path": "Public/Find-PasswordNotification.ps1",
"chars": 1442,
"preview": "function Find-PasswordNotification {\n <#\n .SYNOPSIS\n Searches thru XML logs created by Password Solution\n\n "
},
{
"path": "Public/Find-PasswordQuality.ps1",
"chars": 14998,
"preview": "function Find-PasswordQuality {\n <#\n .SYNOPSIS\n Scan Active Directory forest for asses password quality of use"
},
{
"path": "Public/New-PasswordConfigurationEmail.ps1",
"chars": 8299,
"preview": "function New-PasswordConfigurationEmail {\n [cmdletBinding(DefaultParameterSetName = 'Compatibility', SupportsShouldP"
},
{
"path": "Public/New-PasswordConfigurationEntra.ps1",
"chars": 283,
"preview": "function New-PasswordConfigurationEntra {\n [CmdletBinding()]\n param(\n [switch] $Enable\n )\n $Output ="
},
{
"path": "Public/New-PasswordConfigurationExternalUsers.ps1",
"chars": 2703,
"preview": "function New-PasswordConfigurationExternalUsers {\n <#\n .SYNOPSIS\n This function caches users from external sys"
},
{
"path": "Public/New-PasswordConfigurationOption.ps1",
"chars": 7020,
"preview": "function New-PasswordConfigurationOption {\n <#\n .SYNOPSIS\n Provides a way to create a PasswordConfigurationOpt"
},
{
"path": "Public/New-PasswordConfigurationReplacement.ps1",
"chars": 4048,
"preview": "function New-PasswordConfigurationReplacement {\n <#\n .SYNOPSIS\n Password configuration replacement function fo"
},
{
"path": "Public/New-PasswordConfigurationReport.ps1",
"chars": 8189,
"preview": "function New-PasswordConfigurationReport {\n <#\n .SYNOPSIS\n Provides HTML report configuration for Password Not"
},
{
"path": "Public/New-PasswordConfigurationRule.ps1",
"chars": 12573,
"preview": "function New-PasswordConfigurationRule {\n <#\n .SYNOPSIS\n Short description\n\n .DESCRIPTION\n Long descript"
},
{
"path": "Public/New-PasswordConfigurationRuleReminder.ps1",
"chars": 2848,
"preview": "function New-PasswordConfigurationRuleReminder {\n [CmdletBinding(DefaultParameterSetName = 'Daily')]\n param(\n "
},
{
"path": "Public/New-PasswordConfigurationTemplate.ps1",
"chars": 531,
"preview": "function New-PasswordConfigurationTemplate {\n [CmdletBinding()]\n param(\n [parameter(Mandatory)][ScriptBloc"
},
{
"path": "Public/New-PasswordConfigurationType.ps1",
"chars": 3262,
"preview": "function New-PasswordConfigurationType {\n <#\n .SYNOPSIS\n Configures behavior of password notification emails f"
},
{
"path": "Public/Show-PasswordQuality.ps1",
"chars": 35932,
"preview": "function Show-PasswordQuality {\n <#\n .SYNOPSIS\n Creates an HTML report showing password quality for all user o"
},
{
"path": "Public/Start-PasswordSolution.ps1",
"chars": 17839,
"preview": "function Start-PasswordSolution {\n <#\n .SYNOPSIS\n Starts Password Expiry Notifications for the whole forest\n\n "
},
{
"path": "README.MD",
"chars": 6590,
"preview": "<p align=\"center\">\n <a href=\"https://www.powershellgallery.com/packages/PasswordSolution\"><img src=\"https://img.shield"
}
]
About this extraction
This page contains the full source code of the EvotecIT/PasswordSolution GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 64 files (506.8 KB), approximately 111.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.