mirror of
https://github.com/Grace-Solutions/Invoke-OpenSSHConfiguration.git
synced 2026-07-26 11:38:14 +00:00
825dfdab79
Features added: - Certificate authentication with Windows CA trust bridge - CA filtering via regex inclusion/exclusion expressions - Password authentication disable option - Service auto-start and start management - Config backup before modification (timestamped) - Config validation (sshd -t) with automatic rollback on failure - SFTP subsystem configured by default - Public key management with deduplication - Key pair generation (ed25519, rsa, ecdsa) Toolkit enhancements: - ConvertFrom-CertificateToPEM: Added -IncludePrivateKey, -ThumbprintList, -CreateCABundle - Updated coding standards in PowershellScripts.md Documentation: - Comprehensive README with examples and troubleshooting - Added .augment folder to .gitignore
5.0 KiB
5.0 KiB
type, description
| type | description |
|---|---|
| agent_requested | Use these for powershell scripts |
PowerShell Coding Standards
Output and Logging
- No
Write-Host - No AI icons in log messages and strings
- Only
Write-Verbose,Write-Warning,Write-Error, andWrite-Outputas needed - When using toolkit's
$WriteLogMessage: do NOT add timestamps (handled by scriptblock), do NOT check for null - Centralized logging format:
[TimestampUTC] - [Level] - Message - Use
Start-Transcriptfor script logging (no-Append, no custom log appending functions) - Transcript log name should be based on the
BaseNameof the script
Object Construction
- Use
$Var = New-Object -TypeName 'Type'instead of[Type]::New() - Use
OrderedDictionaryfor building object properties, then cast to PSObject - Use
New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'for splatting parameters - Splatting dictionary properties should be indented one additional level from the variable assignment
Collections
- Use generic lists:
New-Object -TypeName 'System.Collections.Generic.List[System.String]' - Use
.Add()and.AddRange()methods - never use+=for array concatenation - Use
HashSet<T>when checking for existence/uniqueness
Paths and File System
- Use
[System.IO.FileInfo]for file path parameters - Use
[System.IO.DirectoryInfo]for directory path parameters - Build paths with:
[System.IO.FileInfo][System.IO.Path]::Combine(Path1, Path2, Leaf)or[System.IO.DirectoryInfo][System.IO.Path]::Combine(Path1, Path2) - Use
[System.IO.File]::Exists()for file existence checks - Use
[System.IO.Directory]::Exists()for directory existence checks (notTest-Path) - Use environment variable paths like
$Env:ProgramFilesinstead of hardcoded paths like'C:\Program Files' - ScriptPath should be dynamically determined and used for logpath and name
File Encoding
- Use
WriteAllTextorWriteAllLineswith non-BOM encoding - Use ASCII encoding for config files to avoid BOM issues
- PowerShell's
[System.Text.Encoding]::UTF8adds BOM - avoid for config files
URLs and Web Requests
- URLs should be
System.URIwith full scheme (e.g.,https://) - Use
System.Net.WebClientwith default credentials for downloads instead ofInvoke-WebRequest
Conditions and Filtering
Where-Object Syntax
- Always wrap each condition in parentheses
- No spaces after
{or before}
# Correct - Single condition
Where-Object {($_.Type -eq 'CABundle')}
# Correct - Multiple conditions
Where-Object {($_.Type -eq 'CABundle') -and ($_.CertificateCount -gt 0)}
# Incorrect
Where-Object { $_.Type -eq 'CABundle' }
Switch Statements (Preferred over If Statements)
- Use
Switch ($VarName)with{($_ -eq $True)}and{($_ -eq $False)}for single boolean - Use
Switch ($True)only for unrelated conditions - Use
Defaultfor else cases - Set conditional properties when splatting using switch statements
Switch ($SomeCondition)
{
{($_ -eq $True)}
{
# Do something
}
Default
{
# Else case
}
}
Combined Conditions
- Each sub-condition must be wrapped in parentheses
- Use
-eq $Trueexplicitly for switch parameters
# Correct
Switch (($EnableFeature.IsPresent -eq $True) -and ($ConfigExists -eq $True))
# Incorrect
Switch ($EnableFeature.IsPresent -and $ConfigExists)
Code Formatting
- Do NOT put
{on the same line - line break and indent one level - Code inside block indented one more level
- Closing
}at same indent as opening{ - Applies to all blocks: Try/Catch/Finally, Switch, For, Function, etc.
- Nested blocks continue the pattern
Loops
- Use long loop format:
For ($Counter Index etc) {} - Use Counter and Count variables for easy
Write-Progressintegration
Script Structure
- Main script should always have Try/Catch/Finally
- PS7 compatible for Linux/Mac portability (though not the main goal)
- Environment variables only for paths and non-sensitive config, never for secrets/API keys
- Here-strings should use
$($Var)syntax to bake in values at generation time - Service names should be generic to the product, not specific to single use case
String Checks
- Use
([System.String]::IsNullOrEmpty($var) -eq $False)instead of implicit boolean - Use
([System.String]::IsNullOrWhiteSpace($var) -eq $False)when whitespace matters
PowerShell Modules
- No async/await
- No updating progress bars from background threads
- No workarounds without asking first
- Code quality over quick delivery
- Think before implementation - reusable code: BaseCmdlets, inherits, Classes, Models, Methods
- Add Write-Progress to cmdlets where appropriate
- Module folder should NOT be gitignored
- Build artifacts go into
Artifactsfolder - All docs except README go into
docsfolder - Scripts go into
scriptsfolder - Maintain a changelog
- Avoid excessive printing to threads
- Threads should track progress for resume capability
- Release format:
yyyy.mm.dd.hhmm