98 lines
3.8 KiB
PowerShell
98 lines
3.8 KiB
PowerShell
#requires -Version 5.1
|
|
[CmdletBinding()]
|
|
param(
|
|
[switch]$UpdateConfig,
|
|
[string]$ConfigPath
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
if ([string]::IsNullOrWhiteSpace($ConfigPath)) {
|
|
$scriptDirectory = $PSScriptRoot
|
|
if ([string]::IsNullOrWhiteSpace($scriptDirectory) -and
|
|
-not [string]::IsNullOrWhiteSpace($MyInvocation.MyCommand.Path)) {
|
|
$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($scriptDirectory)) {
|
|
throw 'Cannot determine the script directory. Specify -ConfigPath with the full config path.'
|
|
}
|
|
$ConfigPath = Join-Path $scriptDirectory 'appsettings.Development.json'
|
|
}
|
|
|
|
function ConvertTo-EncryptedValue {
|
|
param(
|
|
[Security.SecureString]$Value,
|
|
[byte[]]$AesKey,
|
|
[byte[]]$AesIv
|
|
)
|
|
|
|
$pointer = [IntPtr]::Zero
|
|
$bytes = $null
|
|
$aes = $null
|
|
$encryptor = $null
|
|
try {
|
|
$pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Value)
|
|
$bytes = [Text.Encoding]::UTF8.GetBytes([Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer))
|
|
$aes = [Security.Cryptography.Aes]::Create()
|
|
$aes.Key = $AesKey
|
|
$aes.IV = $AesIv
|
|
$encryptor = $aes.CreateEncryptor()
|
|
$encrypted = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length)
|
|
return 'ENC(' + [Convert]::ToBase64String($encrypted) + ')'
|
|
}
|
|
finally {
|
|
if ($null -ne $encryptor) { $encryptor.Dispose() }
|
|
if ($null -ne $aes) { $aes.Dispose() }
|
|
if ($null -ne $bytes) { [Array]::Clear($bytes, 0, $bytes.Length) }
|
|
if ($pointer -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer) }
|
|
}
|
|
}
|
|
|
|
# Read the same machine variables as CryptoHelper.cs on the deployment server.
|
|
$key = [Text.Encoding]::UTF8.GetBytes([string][Environment]::GetEnvironmentVariable('ENC_AES_KEY', 'Machine'))
|
|
$iv = [Text.Encoding]::UTF8.GetBytes([string][Environment]::GetEnvironmentVariable('ENC_AES_IV', 'Machine'))
|
|
if ($key.Length -notin @(16, 24, 32) -or $iv.Length -ne 16) {
|
|
throw 'ENC_AES_KEY must be 16/24/32 UTF-8 bytes and ENC_AES_IV must be 16 UTF-8 bytes. Run on the deployment server.'
|
|
}
|
|
|
|
$config = $null
|
|
if ($UpdateConfig) {
|
|
$ConfigPath = [IO.Path]::GetFullPath($ConfigPath)
|
|
$config = [IO.File]::ReadAllText($ConfigPath)
|
|
foreach ($field in @('AccessKeyId', 'AccessKeySecret')) {
|
|
if ([regex]::Matches($config, '("' + $field + '"\s*:\s*)"[^"\r\n]*"').Count -ne 1) {
|
|
throw "Expected exactly one $field field in the config. No changes were made."
|
|
}
|
|
}
|
|
}
|
|
|
|
$id = $null
|
|
$secret = $null
|
|
try {
|
|
$id = Read-Host 'Enter the complete RAM user AccessKey ID (hidden input)' -AsSecureString
|
|
$secret = Read-Host 'Enter the complete RAM user AccessKey Secret (hidden input)' -AsSecureString
|
|
if ($id.Length -eq 0 -or $secret.Length -eq 0) {
|
|
throw 'AccessKey ID and AccessKey Secret cannot be empty. No changes were made.'
|
|
}
|
|
|
|
$encryptedId = ConvertTo-EncryptedValue -Value $id -AesKey $key -AesIv $iv
|
|
$encryptedSecret = ConvertTo-EncryptedValue -Value $secret -AesKey $key -AesIv $iv
|
|
|
|
if ($UpdateConfig) {
|
|
$config = [regex]::Replace($config, '("AccessKeyId"\s*:\s*)"[^"\r\n]*"', '${1}"' + $encryptedId + '"')
|
|
$config = [regex]::Replace($config, '("AccessKeySecret"\s*:\s*)"[^"\r\n]*"', '${1}"' + $encryptedSecret + '"')
|
|
[IO.File]::WriteAllText($ConfigPath, $config, [Text.UTF8Encoding]::new($false))
|
|
Write-Host 'Encrypted credentials saved. Deploy the updated config and restart the service.'
|
|
}
|
|
else {
|
|
Write-Output ('AccessKeyId: ' + $encryptedId)
|
|
Write-Output ('AccessKeySecret: ' + $encryptedSecret)
|
|
}
|
|
}
|
|
finally {
|
|
if ($null -ne $id) { $id.Dispose() }
|
|
if ($null -ne $secret) { $secret.Dispose() }
|
|
[Array]::Clear($key, 0, $key.Length)
|
|
[Array]::Clear($iv, 0, $iv.Length)
|
|
}
|