Add restricted Windows Gitea runner setup
Some checks failed
OfficeCom Sentinel Client / validate-client (push) Successful in 25s
OfficeCom Sentinel Client / build-client-windows (push) Has been cancelled

This commit is contained in:
OfficeCom Codex
2026-07-25 01:31:00 +02:00
parent 1ad720f919
commit ea90ddd1f6

View File

@@ -0,0 +1,124 @@
[CmdletBinding()]
param(
[string]$RegistrationToken,
[string]$InstanceUrl = "https://gitea.officecom.cloud",
[string]$RunnerName = "officecom-oc-sentinel-windows-01",
[string]$RunnerVersion = "1.0.8",
[string]$RunnerAccount = "OCGiteaRunner",
[string]$InstallRoot = "$env:ProgramData\\OCGiteaRunner"
)
$ErrorActionPreference = "Stop"
function Test-IsAdministrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function New-RunnerPassword {
# The account is only used by Task Scheduler; no password is persisted in this script or repository.
$bytes = New-Object byte[] 36
[Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
return [Convert]::ToBase64String($bytes).Replace('+', 'A').Replace('/', 'B').Replace('=', 'C') + "!9z"
}
if (-not (Test-IsAdministrator)) {
throw "Run this script from an elevated PowerShell window (Run as administrator)."
}
if ([string]::IsNullOrWhiteSpace($RegistrationToken)) {
$secureToken = Read-Host "Paste the repository runner registration token" -AsSecureString
$tokenPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureToken)
try {
$RegistrationToken = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($tokenPointer)
}
finally {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($tokenPointer)
}
}
if ([string]::IsNullOrWhiteSpace($RegistrationToken)) {
throw "A repository runner registration token is required."
}
$taskName = "OCSentinel Gitea Windows Runner"
$runnerPath = Join-Path $InstallRoot "gitea-runner.exe"
$configPath = Join-Path $InstallRoot "config.yaml"
$runnerStatePath = Join-Path $InstallRoot ".runner"
$logDirectory = Join-Path $InstallRoot "logs"
$downloadUrl = "https://gitea.com/gitea/act_runner/releases/download/v$RunnerVersion/gitea-runner-$RunnerVersion-windows-amd64.exe"
$checksumUrl = "$downloadUrl.sha256"
$accountQualifiedName = "$env:COMPUTERNAME\\$RunnerAccount"
if (Test-Path -LiteralPath $runnerStatePath) {
throw "A runner is already registered at $InstallRoot. Remove it in Gitea first, then remove this directory if a new registration is needed."
}
$existingAccount = Get-LocalUser -Name $RunnerAccount -ErrorAction SilentlyContinue
if ($existingAccount) {
throw "The local account '$RunnerAccount' already exists. Stop and remove the existing runner before reinstalling it."
}
New-Item -ItemType Directory -Force -Path $InstallRoot, $logDirectory | Out-Null
try {
Write-Host "Downloading Gitea runner $RunnerVersion..."
Invoke-WebRequest -UseBasicParsing -Uri $downloadUrl -OutFile $runnerPath
$checksumText = (Invoke-WebRequest -UseBasicParsing -Uri $checksumUrl).Content.Trim()
$expectedHash = ($checksumText -split '\s+')[0].ToLowerInvariant()
$actualHash = (Get-FileHash -LiteralPath $runnerPath -Algorithm SHA256).Hash.ToLowerInvariant()
if ($actualHash -ne $expectedHash) {
throw "Runner checksum verification failed."
}
$password = New-RunnerPassword
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
New-LocalUser -Name $RunnerAccount -Password $securePassword -Description "Restricted account for the OCSentinel Gitea Actions runner." -AccountNeverExpires | Out-Null
$config = & $runnerPath generate-config
$config = $config -replace '(?m)^ labels:.*$', ' labels: ["windows:host"]'
Set-Content -LiteralPath $configPath -Value $config -Encoding utf8
# Build jobs run only with this non-administrative account and only for the repository runner token supplied.
$acl = Get-Acl -LiteralPath $InstallRoot
$acl.SetAccessRuleProtection($true, $false)
$systemRule = New-Object Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$adminRule = New-Object Security.AccessControl.FileSystemAccessRule("BUILTIN\\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$runnerRule = New-Object Security.AccessControl.FileSystemAccessRule($accountQualifiedName, "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")
$acl.AddAccessRule($systemRule)
$acl.AddAccessRule($adminRule)
$acl.AddAccessRule($runnerRule)
Set-Acl -LiteralPath $InstallRoot -AclObject $acl
$credential = New-Object Management.Automation.PSCredential($accountQualifiedName, $securePassword)
$registerArgs = @(
"--config", "`"$configPath`"", "register", "--no-interactive",
"--instance", "`"$InstanceUrl`"", "--token", "`"$RegistrationToken`"",
"--name", "`"$RunnerName`"", "--labels", "windows:host"
) -join " "
$registration = Start-Process -FilePath $runnerPath -ArgumentList $registerArgs -WorkingDirectory $InstallRoot -Credential $credential -Wait -PassThru
if ($registration.ExitCode -ne 0 -or -not (Test-Path -LiteralPath $runnerStatePath)) {
throw "Runner registration failed with exit code $($registration.ExitCode)."
}
$action = New-ScheduledTaskAction -Execute $runnerPath -Argument "--config `"$configPath`" daemon" -WorkingDirectory $InstallRoot
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $accountQualifiedName -Password $password -RunLevel Limited -Description "Runs the repository-scoped OCSentinel Gitea Actions runner." -Force | Out-Null
Start-ScheduledTask -TaskName $taskName
Start-Sleep -Seconds 3
$task = Get-ScheduledTask -TaskName $taskName
Write-Host "Gitea runner installed successfully."
Write-Host "Runner: $RunnerName"
Write-Host "Labels: windows:host"
Write-Host "Task: $taskName ($($task.State))"
Write-Host "Install path: $InstallRoot"
}
catch {
if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) {
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
}
throw
}