WinBatchOrchestrator.psm1
|
# WinBatchOrchestrator.psm1 function Initialize-OrchestratorEnvironment { <# .SYNOPSIS Initializes the C:\Ops environment. .PARAMETER ServiceAccount The service account user to grant access to secrets. #> param ( [string]$ServiceAccount ) $OpsRoot = "C:\Ops" $Dirs = @("Bin", "Scripts", "Logs", "Secrets") foreach ($Dir in $Dirs) { $Path = Join-Path $OpsRoot $Dir if (-not (Test-Path $Path)) { New-Item -ItemType Directory -Path $Path -Force | Out-Null Write-Host "Created $Path" } } # Event Source Creation (Requires Admin) $EventSource = "WinBatchOrchestrator" try { if (-not ([System.Diagnostics.EventLog]::SourceExists($EventSource))) { New-EventLog -LogName Application -Source $EventSource Write-Host "Created Event Source: $EventSource" } } catch { Write-Warning "Could not check or create Event Source '$EventSource'. Ensure you are running as Administrator if this is the first run. Error: $_" } # Version Check & Asset Deployment $ModuleRoot = $PSScriptRoot $AssetsDir = Join-Path $ModuleRoot "Assets" $VersionFile = Join-Path $OpsRoot "Bin\version.txt" $CurrentVersion = $MyInvocation.MyCommand.Module.Version.ToString() $DeployedVersion = "0.0.0" if (Test-Path $VersionFile) { $DeployedVersion = Get-Content -Path $VersionFile -Raw } if ($CurrentVersion -ne $DeployedVersion) { Write-Host "Upgrading Assets from $DeployedVersion to $CurrentVersion..." if (Test-Path $AssetsDir) { # Copy everything except Dashboard to Bin Get-ChildItem -Path $AssetsDir -Exclude "Dashboard" | Copy-Item -Destination "$OpsRoot\Bin" -Recurse -Force # Deploy Dashboard $DashboardAsset = Join-Path $AssetsDir "Dashboard" $DashboardDest = Join-Path $OpsRoot "Dashboard" if (Test-Path $DashboardAsset) { if (-not (Test-Path $DashboardDest)) { New-Item -ItemType Directory -Path $DashboardDest -Force | Out-Null } Copy-Item -Path "$DashboardAsset\*" -Destination $DashboardDest -Recurse -Force Write-Host "Deployed Dashboard to $DashboardDest" } $CurrentVersion | Set-Content -Path $VersionFile Write-Host "Deployed Assets to $OpsRoot\Bin" } } else { Write-Host "Assets are up to date ($CurrentVersion)." } # Move Templates (Always ensure they are present) $Templates = Get-ChildItem -Path "$OpsRoot\Bin" -Filter "Template-*" foreach ($Template in $Templates) { $Dest = Join-Path "$OpsRoot\Scripts" $Template.Name if (-not (Test-Path $Dest)) { Move-Item -Path $Template.FullName -Destination "$OpsRoot\Scripts" -Force Write-Host "Moved Template $($Template.Name) to $OpsRoot\Scripts" } } # Security for Secrets $SecretsPath = Join-Path $OpsRoot "Secrets" $Acl = Get-Acl -Path $SecretsPath # Disable inheritance and copy existing rules $Acl.SetAccessRuleProtection($true, $false) # Grant Admin/System Full Control $AdminRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") $SystemRule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") $Acl.AddAccessRule($AdminRule) $Acl.AddAccessRule($SystemRule) # Grant Service Account Read/Execute if provided if (-not [string]::IsNullOrWhiteSpace($ServiceAccount)) { $ServiceRule = New-Object System.Security.AccessControl.FileSystemAccessRule($ServiceAccount, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow") $Acl.AddAccessRule($ServiceRule) } Set-Acl -Path $SecretsPath -AclObject $Acl Write-Host "Secured $SecretsPath" # Register Maintenance Task (Cleanup Logs) $CleanupScript = "C:\Ops\Bin\Cleanup-OpsLogs.ps1" if (Test-Path -Path $CleanupScript) { $Params = @{ JobName = "OpsMaintenance-LogCleanup" ScriptPath = $CleanupScript ScheduleTime = [datetime]::Parse("02:00") ScriptArguments = @("-DaysToKeep", "30") } if (-not [string]::IsNullOrWhiteSpace($ServiceAccount)) { $Params["ServiceAccountUser"] = $ServiceAccount } # Use the internal helper or call the script directly if function not available in scope yet & "C:\Ops\Bin\New-OpsJob.ps1" @Params Write-Host "Registered Maintenance Task: OpsMaintenance-LogCleanup" } } # End of Initialize-OrchestratorEnvironment function Invoke-OpsScript { param ( [string]$ScriptName, [hashtable]$Arguments = @{} ) $ScriptPath = Join-Path "C:\Ops\Bin" $ScriptName if (-not (Test-Path $ScriptPath)) { throw "Script not found: $ScriptPath. Run Initialize-OrchestratorEnvironment first." } & $ScriptPath @Arguments } # Proxy Functions function New-OpsJob { [CmdletBinding()] param( [Parameter(Mandatory=$true)][string]$JobName, [Parameter(Mandatory=$true)][string]$ScriptPath, [Parameter(Mandatory=$true)][datetime]$ScheduleTime, [string]$ServiceAccountUser, [timespan]$Interval, [string[]]$ScriptArguments, [string[]]$EmailRecipients, [string]$AlertWebhookUrl, [string[]]$RequiredSecrets ) Invoke-OpsScript -ScriptName "New-OpsJob.ps1" -Arguments $PSBoundParameters } function Register-OpsJobs { [CmdletBinding()] param([Parameter(Mandatory=$true)][string]$ConfigPath) Invoke-OpsScript -ScriptName "Register-OpsJobs.ps1" -Arguments $PSBoundParameters } function New-OpsCreds { [CmdletBinding()] param([Parameter(Mandatory=$true)][string]$Name) Invoke-OpsScript -ScriptName "New-OpsCreds.ps1" -Arguments $PSBoundParameters } function Get-OpsJob { [CmdletBinding()] param([string]$JobName) Invoke-OpsScript -ScriptName "Get-OpsJob.ps1" -Arguments $PSBoundParameters } function Start-OpsJob { [CmdletBinding()] param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)][string]$JobName) process { Invoke-OpsScript -ScriptName "Start-OpsJob.ps1" -Arguments @{ JobName = $JobName } } } function Stop-OpsJob { [CmdletBinding()] param([Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string]$JobName) process { Invoke-OpsScript -ScriptName "Stop-OpsJob.ps1" -Arguments @{ JobName = $JobName } } } function Remove-OpsJob { [CmdletBinding()] param([Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string]$JobName) process { Invoke-OpsScript -ScriptName "Remove-OpsJob.ps1" -Arguments @{ JobName = $JobName } } } function Get-OpsJobHistory { [CmdletBinding()] param([string]$JobName, [int]$Count) Invoke-OpsScript -ScriptName "Get-OpsJobHistory.ps1" -Arguments $PSBoundParameters } function Get-OpsJobLog { [CmdletBinding()] param([string]$JobName, [int]$Count) Invoke-OpsScript -ScriptName "Get-OpsJobLog.ps1" -Arguments $PSBoundParameters } Export-ModuleMember -Function Initialize-OrchestratorEnvironment, New-OpsJob, Register-OpsJobs, New-OpsCreds, Get-OpsJob, Start-OpsJob, Stop-OpsJob, Remove-OpsJob, Get-OpsJobHistory, Get-OpsJobLog |