param( [string]$Username = '', [ValidateSet('production', 'demo')][string]$Mode = 'production' ) . (Join-Path $PSScriptRoot 'sense-common.ps1') $passwordPointer = [IntPtr]::Zero try { $root = Get-SensePackageRoot $state = Initialize-SenseRuntime -PackageRoot $root -Mode $Mode -AllowOccupiedPort $token = Get-SenseEnvironmentValue -Name 'SENSE_BOOTSTRAP_TOKEN' if ($token.Length -lt 32) { throw 'Set a temporary random SENSE_BOOTSTRAP_TOKEN of at least 32 characters, then restart Sense.' } if ([string]::IsNullOrWhiteSpace($Username)) { $Username = Read-Host 'Administrator username' } $securePassword = Read-Host 'Administrator password (at least 6 characters)' -AsSecureString $passwordPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePassword) $password = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($passwordPointer) $body = @{ username = $Username; password = $password; nickName = $Username } | ConvertTo-Json -Compress $headers = @{ 'X-Sense-Bootstrap-Token' = $token } $uri = "http://$($state.Host):$($state.Port)/api/v1/public/bootstrap" Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -ContentType 'application/json; charset=utf-8' -Body $body | Out-Null Write-Host 'Sense administrator created. Remove SENSE_BOOTSTRAP_TOKEN from config/sense.env and restart Sense now.' exit 0 } catch { Write-Error $_.Exception.Message exit 1 } finally { if ($passwordPointer -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($passwordPointer) } Remove-Variable password -ErrorAction SilentlyContinue }