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
133 lines
5.0 KiB
Markdown
133 lines
5.0 KiB
Markdown
---
|
|
type: "agent_requested"
|
|
description: "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`, and `Write-Output` as 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-Transcript` for script logging (no `-Append`, no custom log appending functions)
|
|
- Transcript log name should be based on the `BaseName` of the script
|
|
|
|
## Object Construction
|
|
- Use `$Var = New-Object -TypeName 'Type'` instead of `[Type]::New()`
|
|
- Use `OrderedDictionary` for 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 (not `Test-Path`)
|
|
- Use environment variable paths like `$Env:ProgramFiles` instead of hardcoded paths like `'C:\Program Files'`
|
|
- ScriptPath should be dynamically determined and used for logpath and name
|
|
|
|
## File Encoding
|
|
- Use `WriteAllText` or `WriteAllLines` with non-BOM encoding
|
|
- Use ASCII encoding for config files to avoid BOM issues
|
|
- PowerShell's `[System.Text.Encoding]::UTF8` adds BOM - avoid for config files
|
|
|
|
## URLs and Web Requests
|
|
- URLs should be `System.URI` with full scheme (e.g., `https://`)
|
|
- Use `System.Net.WebClient` with default credentials for downloads instead of `Invoke-WebRequest`
|
|
|
|
## Conditions and Filtering
|
|
|
|
### Where-Object Syntax
|
|
- Always wrap each condition in parentheses
|
|
- No spaces after `{` or before `}`
|
|
|
|
```powershell
|
|
# 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 `Default` for else cases
|
|
- Set conditional properties when splatting using switch statements
|
|
|
|
```powershell
|
|
Switch ($SomeCondition)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
# Do something
|
|
}
|
|
|
|
Default
|
|
{
|
|
# Else case
|
|
}
|
|
}
|
|
```
|
|
|
|
### Combined Conditions
|
|
- Each sub-condition must be wrapped in parentheses
|
|
- Use `-eq $True` explicitly for switch parameters
|
|
|
|
```powershell
|
|
# 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-Progress` integration
|
|
|
|
## 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 `Artifacts` folder
|
|
- All docs except README go into `docs` folder
|
|
- Scripts go into `scripts` folder
|
|
- Maintain a changelog
|
|
- Avoid excessive printing to threads
|
|
- Threads should track progress for resume capability
|
|
- Release format: `yyyy.mm.dd.hhmm`
|