Created
June 16, 2025 14:38
-
-
Save infamousjoeg/4683452365e6c5449bfea8d706935727 to your computer and use it in GitHub Desktop.
Proxy-supported Vault-Conjur Synchronizer PowerShell Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Version = 13.6.0.4-release/13.6 | |
#----------------------------------------- | |
# This script installs the Vault-Conjur Synchronizer | |
#------------------------------------------ | |
#Requires -Version 4.0 | |
param([switch] $silent, [switch] $forceNoPVWAApiUse, [switch] $trustPVWAAndConjurCert, [switch] $automationTests) | |
#region [Variables] | |
$script:ScriptDir = $null | |
$script:LogFilePath = $null | |
$script:LogFolderPath = $null | |
$script:doesPVWAAPIExist = $false | |
$script:ConjurDatabaseUsername = $null | |
$script:ConjurDatabasePassword = $null | |
$script:ConjurDatabasePort = $null | |
$script:ConjurDatabaseHost = $null | |
$script:Config=@{} | |
$script:InstallationTargetPathParameter="InstallationTargetPath" | |
$script:PVWAURLParameter="PVWAURL" | |
$script:ConjurServerDNSParameter="ConjurServerDNS" | |
$script:VaultNameParameter="VaultName" | |
$script:VaultAddressParameter="VaultAddress" | |
$script:VaultPortParameter="VaultPort" | |
$script:SyncSafeNameParameter="SyncSafeName" | |
$script:ConjurCredentialsFilePathParameter="ConjurCredentialsFilePath" | |
$script:ConjurAccountKeyParameter="ConjurAccount" | |
$script:ConjurAuthenApiKeyParameter="ConjurAuthnApi" | |
$script:ConjurAuthenUserKeyParameter="ConjurAuthnUser" | |
$script:ConjurTokenKeyParameter="ConjurTokenKey" | |
$script:LOBNameParameter="LOBName" | |
$script:LOBPlatformParameter="LOBPlatform" | |
$script:MultiNodeEnabledParameter="MultiNodeEnabled" | |
$script:ClusterKeyParameter="ClusterKey" | |
$script:ConjurCloudSelectedParameter="ConjurCloudSelected"; | |
$script:ConjurCloudHostAndTokenParameter="ConjurCloudHostAndToken"; | |
$script:HostPrefix = "host/" | |
#Constants | |
$SyncPrefix = 'Sync_' | |
$LobAccountPrefix = "LOBUser_" | |
$ConjurCloudDefaultLob = 'ConjurSync' | |
#endregion | |
#region [Functions] | |
function VerifyScriptsSignature { | |
param($ScriptDir) | |
$scriptPath = "$ScriptDir\V5SynchronizerInstallation.ps1" | |
$scriptsToVerify = @( | |
"$ScriptDir\Modules\PVWAapi.Gen1.URIS.psm1", | |
"$ScriptDir\Modules\PVWAapi.Gen2.URIS.psm1", | |
"$ScriptDir\Modules\PVWAapi.ps1", | |
"$ScriptDir\Modules\PVWAapi.RestService.psm1", | |
"$ScriptDir\Modules\PVWAapi.Utils.psm1", | |
"$ScriptDir\Modules\SynchronizerBase.ps1", | |
"$ScriptDir\Modules\Strategies\PVWAapi.gen2.psm1", | |
"$ScriptDir\Modules\Strategies\PVWAapi.mixed.psm1" | |
) | |
foreach ($scriptToVerify in $scriptsToVerify) { | |
VerifyScriptModuleCertificate $scriptPath $scriptToVerify | |
} | |
} | |
function VerifyScriptModuleCertificate{ | |
param($scriptPath, $modulePath) | |
$signatureScript = Get-AuthenticodeSignature -FilePath $scriptPath | |
$signatureScriptModule = Get-AuthenticodeSignature -FilePath $modulePath | |
if($signatureScript.Status -eq "Valid"){ | |
if($signatureScriptModule.Status -eq "Valid"){ | |
$scriptSubject = ($signatureScript | select -ExpandProperty SignerCertificate).thumbprint | |
$scriptModuleSubject = ($signatureScriptModule | select -ExpandProperty SignerCertificate).thumbprint | |
if($scriptSubject -ne $scriptModuleSubject){ | |
Write-Error "The $modulePath certificate is not trusted to work with this script. Make sure its source is trusted." | |
Exit 1 | |
} | |
} | |
else{ | |
Write-Error "The $modulePath certificate is not trusted. Make sure its source is trusted." | |
Exit 1 | |
} | |
} | |
elseif($signatureScript.Status -ne "NotSigned"){ | |
Write-Error 'Error: The script you are using is unsafe. Make sure its source is trusted.' | |
Exit 1 | |
} | |
} | |
# Sets the value in the config | |
function SetValueInConfig($key, $value){ | |
if($silent -and $Config.ContainsKey($key)){ | |
return | |
} | |
$Config.Add($key, $value) | |
} | |
# Replace the value in the config | |
function ReplaceValueInConfig($key, $value){ | |
$Config[$key] = $value | |
} | |
# Returns the value from the config | |
function GetValueFromConfig($key){ | |
return $Config.Get_Item($key) | |
} | |
# ----------------- Get Conjur Database configuration from Conjur ----------------- | |
function GetDatabaseConfigurationFromConjur() { | |
LogMsg -Msg $UserMessages.SynchronizerDatabasePolicy -newLine | |
$conjurAccountEncoded = [System.Web.HttpUtility]::UrlEncode($conjurAccount) | |
$variablePath = "$conjurAccountEncoded`:variable`:AutomationVault/db" | |
$conjurDatabaseConfiguration = GetConjurDatabaseConfiguration -variablePath $variablePath | |
MapConfigurationToVariables -databaseConfigurationFromConjur $conjurDatabaseConfiguration -variablePath $variablePath | |
} | |
function MapConfigurationToVariables($databaseConfigurationFromConjur, $variablePath) { | |
$variablesArray = $databaseConfigurationFromConjur -replace '@\{|}', '' -split '; ' | |
foreach ($variable in $variablesArray) { | |
$name, $value = $variable -split '=' | |
switch ($name) | |
{ | |
"$variablePath/password" {$script:ConjurDatabasePassword = $value; Break} | |
"$variablePath/username" {$script:ConjurDatabaseUsername = $value; Break} | |
"$variablePath/url" {$script:ConjurDatabaseHost = $value -split ':' |Select-Object -First 1; $script:ConjurDatabasePort = $value -split ':' |Select-Object -Last 1; Break} | |
} | |
} | |
} | |
# Map configuration to variables: | |
# Get data from conjur | |
function GetConjurDatabaseConfiguration($variablePath) { | |
$baseUri = GetBaseUriForConjurApi -parameterName $ConjurServerDNSParameter | |
$conjurToken = (GetValueFromConfig -key $ConjurTokenKeyParameter) | |
$variables = "$variablePath/password,$variablePath/url,$variablePath/username" | |
$hostUri = "$baseUri/secrets?variable_ids=$variables" | |
try{ | |
return Invoke-RestMethod @proxyConfig -Uri $hostUri -Headers @{"Authorization"="Token token=`"$conjurToken`""; "UserAgent"="Powershell"} | |
} | |
catch{ | |
$statusCode = $_.Exception.Response.StatusCode.Value__ | |
if($statusCode -eq 404){ | |
throw $UserMessages.ConjurDatabaseConfigurationNotFound | |
} | |
else{ | |
$CouldntRetretrieveDatabaseConfigurationFromConjur = [string]::Format($UserMessages.CouldNotRetrieveDatabaseConfigurationFromConjur, $statusCode) | |
throw $CouldntRetretrieveDatabaseConfigurationFromConjur | |
} | |
} | |
} | |
# ----------------- Create Conjur Host and Policy ----------------- | |
# Creates a policy file with a host for the Synchronizer and vault policy loads it to Conjur | |
function CreateConjurHostAndPolicy($conjurHostId, $conjurHostCredFileOutputPath, $vaultName){ | |
LogMsg -Msg $UserMessages.SynchronizerPolicy -newLine | |
# Check if host already exists in Conjur | |
$baseUri = GetBaseUriForConjurApi -parameterName $ConjurServerDNSParameter | |
$conjurToken = (GetValueFromConfig -key $ConjurTokenKeyParameter) | |
$conjurHostIdEncoded = [System.Web.HttpUtility]::UrlEncode($conjurHostId) | |
$conjurAccountEncoded = [System.Web.HttpUtility]::UrlEncode($conjurAccount) | |
$isHostExists = $false | |
$hostUri = "$baseUri/resources/$conjurAccountEncoded/$script:HostPrefix$conjurHostIdEncoded" | |
try{ | |
$searchHostResponse = Invoke-RestMethod @proxyConfig -Uri $hostUri -Headers @{"Authorization"="Token token=`"$conjurToken`""; "UserAgent"="Powershell"} | |
$ConjurHostAlreadyExistsMessage = [string]::Format($UserMessages.ConjurHostAlreadyExists, $conjurHostId) | |
LogMsg -Type Debug -Msg $ConjurHostAlreadyExistsMessage | |
$isHostExists = $true | |
} | |
catch{ | |
$statusCode = $_.Exception.Response.StatusCode.Value__ | |
if($statusCode -ne 404){ | |
$CouldntCreateHostFailedExistenceSearchMessage = [string]::Format($UserMessages.CouldntCreateHostFailedExistenceSearch, $conjurHostId, $searchHostResponse, $_.ErrorDetails) | |
throw $CouldntCreateHostFailedExistenceSearchMessage | |
} | |
} | |
# Create host and policy | |
$policyFileContent = createHostPolicyFileContent | |
$groupUri = "$baseUri/resources/$conjurAccountEncoded/group/synchronizer" | |
$doesSynchronizerGroupExist = ConjurGroupExists $groupUri $conjurToken | |
if($doesSynchronizerGroupExist){ | |
$grantSyncGroupPolicyFileContent = CreateSynchronizerGroupPolicyFileContent | |
$policyFileContent = "$policyFileContent`n$grantSyncGroupPolicyFileContent" | |
} | |
$loadPolicyUri = "$baseUri/policies/$conjurAccountEncoded/policy/root" | |
try{ | |
$createHostResponse = Invoke-RestMethod @proxyConfig -Method Post -Uri $loadPolicyUri -Headers @{"Authorization"="Token token=`"$conjurToken`""; "UserAgent"="Powershell"} -Body $policyFileContent | |
} | |
catch{ | |
$statusCode = $_.Exception.Response.StatusCode.Value__ | |
$CouldntCreateHostFailedToLoadPolicyMessage = [string]::Format($UserMessages.CouldntCreateHostFailedToLoadPolicy, $conjurHostId, $createHostResponse, $statusCode, $_.ErrorDetails) | |
throw $CouldntCreateHostFailedToLoadPolicyMessage | |
} | |
if(-not $isHostExists){ | |
try{ | |
$hostParamKey = "$conjurAccount`:host`:$conjurHostId" | |
$Script:objectApiKey = $createHostResponse.created_roles.$hostParamKey.api_key | |
if(-not $Script:objectApiKey){ | |
throw | |
} | |
if($forceNoPVWAApiUse -or -not $doesPVWAAPIExist){ | |
createConjurHostCredFile $conjurHostId $objectApiKey $conjurHostCredFileOutputPath | |
} | |
} | |
catch{ | |
throw $UserMessages.FailedToParseResponseFromLoadPolicy | |
} | |
if($automationTests){ | |
createConjurHostCredFile $conjurHostId $Script:objectApiKey $conjurHostCredFileOutputPath | |
} | |
} | |
elseif(-not $forceNoPVWAApiUse -and $doesPVWAAPIExist){ | |
$rotateHostAPIKeyUri = "$baseUri/authn/$conjurAccountEncoded/api_key?role=host:$conjurHostIdEncoded" | |
try{ | |
$Script:objectApiKey = Invoke-RestMethod @proxyConfig -Method PUT -Uri $rotateHostAPIKeyUri -Headers @{"Authorization"="Token token=`"$conjurToken`""; "UserAgent"="Powershell"} | |
} | |
catch{ | |
$statusCode = $_.Exception.Response.StatusCode.Value__ | |
$FailedToRotateAPIKeyMessage = [string]::Format($UserMessages.FailedToRotateAPIKey, $hostParamKey, $rotateHostAPIKeyUri, $_.ErrorDetails) | |
throw $FailedToRotateAPIKeyMessage | |
} | |
if($automationTests){ | |
createConjurHostCredFile $conjurHostId $Script:objectApiKey $conjurHostCredFileOutputPath | |
} | |
} | |
} | |
# ----------------- Create Conjur Host and Policy ----------------- | |
# Creates a policy file with a host for the Synchronizer and vault policy loads it to Conjur | |
# conjurHostFileOutputPath is the path to the file that will contain the host credentials | |
function RotateConjurCloudApiKey($conjurHostId, $conjurHostFileOutputPath){ | |
LogMsg -Msg $UserMessages.ConjurCloudApiKeyRotation -newLine | |
$conjurToken = (GetValueFromConfig -key $ConjurTokenKeyParameter) | |
$hostWithoutHostPrefix = $conjurHostId -replace "^host/", "" | |
$conjurHostIdEncoded = [System.Web.HttpUtility]::UrlEncode($hostWithoutHostPrefix) | |
$conjurAccountEncoded = [System.Web.HttpUtility]::UrlEncode($conjurAccount) | |
$baseUri = GetBaseUriForConjurApi -parameterName $ConjurServerDNSParameter | |
$rotateHostAPIKeyUri = "$baseUri/authn/$conjurAccountEncoded/api_key?role=host:$conjurHostIdEncoded" | |
try{ | |
$Script:objectApiKey = Invoke-RestMethod @proxyConfig -Method PUT -Uri $rotateHostAPIKeyUri -Headers @{"Authorization"="Token token=`"$conjurToken`""; "UserAgent"="Powershell"} | |
} | |
catch{ | |
$statusCode = $_.Exception.Response.StatusCode.Value__ | |
$FailedToRotateAPIKeyMessage = [string]::Format($UserMessages.FailedToRotateAPIKey, $conjurHostId, $rotateHostAPIKeyUri, $_.ErrorDetails) | |
throw $FailedToRotateAPIKeyMessage | |
} | |
if($automationTests){ | |
createConjurHostCredFile -conjurHostId $conjurHostId -objectApiKey $Script:objectApiKey -conjurHostCredFileOutputPath $conjurHostFileOutputPath | |
} | |
} | |
function createHostPolicyFileContent() | |
{ | |
if ((GetValueFromConfig -key $ConjurCloudSelectedParameter) -eq $true) { | |
# This should not happen because this method is not invoked for Conjur Cloud. | |
# It is here to prevent the method from being called in case of a bug. | |
LogMsg -Type Error -Msg $UserMessages.ConjurCloudNoHostCreation | |
exit 1 | |
} | |
$synchronizerVersion = getSynchronizerVersion | |
return @" | |
- !group | |
id: $vaultName-admins | |
- !host | |
id: $conjurHostId | |
annotations: | |
authn/api-key: true | |
synchronzer-user: true | |
synchronizer-version: $synchronizerVersion | |
- !grant | |
role: !group $vaultName-admins | |
members: | |
- !host $conjurHostId | |
- !policy | |
id: $vaultName | |
owner: !group $vaultName-admins | |
"@ | |
} | |
function CreateSynchronizerGroupPolicyFileContent() { | |
$policyFileContent = @" | |
- !grant | |
role: !group synchronizer | |
members: | |
- !host $conjurHostId | |
"@ | |
return $policyFileContent | |
} | |
function getSynchronizerVersion() { | |
$version = (Get-Command "$ScriptDir\..\VaultConjurSynchronizer\VaultConjurSynchronizer.exe").FileVersionInfo | |
$versionString = [string]::Format("{0}.{1}.{2}", $version.FileMajorPart, $version.FileMinorPart, $version.FileBuildPart) | |
return $versionString | |
} | |
function createConjurHostCredFile($conjurHostId, $objectApiKey, $conjurHostCredFileOutputPath){ | |
$psHostname = "$script:HostPrefix$conjurHostId" | |
$psApiKey = ConvertTo-SecureString -String $objectApiKey -AsPlainText -Force | |
$psCredentials = New-Object System.Management.Automation.PSCredential ($psHostname, $psApiKey) | |
CreatePSCredentials -PSCredentials $psCredentials -outputPath $conjurHostCredFileOutputPath | |
$ConjurHostCredentialsWrittenMessage = [string]::Format($UserMessages.ConjurHostCredentialsWritten, $conjurHostCredFileOutputPath) | |
LogMsg -Msg $ConjurHostCredentialsWrittenMessage | |
} | |
# ----------------- Init Conjur ----------------- | |
# Initialize Conjur by sending authentication REST requests to the prompted hostname | |
function InitConjur(){ | |
LogMsg -Msg $UserMessages.ConjurAuthentication -newLine | |
if($silent){ | |
if($forceNoPVWAApiUse -or -not $doesPVWAAPIExist){ | |
VerifyMandatoryParam -key $ConjurCredentialsFilePathParameter | |
$conjurCredentials = Import-Clixml -Path (GetValueFromConfig -key $ConjurCredentialsFilePathParameter) | |
} | |
#$conjurCredentials is an environment variable in new mode | |
if($null -eq $conjurCredentials){ | |
Write-Error $UserMessages.ConjurLogonNoCredentials | |
exit 1 | |
} | |
$conjurUser = $conjurCredentials.UserName | |
$conjurApiKey = ConvertSecurePasswordToPlainText -securePassword $conjurCredentials.Password | |
$ConjurServerDNS = (GetValueFromConfig -key $ConjurServerDNSParameter) | |
$conjurAccount = (GetValueFromConfig -key $ConjurAccountKeyParameter) | |
} | |
else{ | |
$ConjurServerDNS = ReadHost $UserMessages.ConjurServerHostNameSpecify | |
$script:conjurAccount = ReadHost $UserMessages.ConjurAccountNameSpecify | |
$conjurUser = ReadHostWithDefaultValue -Message $UserMessages.ConjurUserNameSpecify -defaultValue $UserMessages.VaultDefaultAdminUser | |
$conjurUserPassword = GetPassword -userPromptMsg $UserMessages.ConjurAPIKeySpecify | |
$conjurApiKey = ConvertSecurePasswordToPlainText -securePassword $conjurUserPassword | |
SetValueInConfig -key $ConjurAccountKeyParameter -value $conjurAccount | |
} | |
ReplaceValueInConfig -key $ConjurServerDNSParameter -value "$ConjurServerDNS" | |
$script:ConjurServerDNS = (GetValueFromConfig -key $ConjurServerDNSParameter) | |
SetValueInConfig -key $ConjurAuthenUserKeyParameter -value $conjurUser | |
SetValueInConfig -key $ConjurAuthenApiKeyParameter -value $conjurApiKey | |
$encodedConjurAccount = [System.Web.HttpUtility]::UrlEncode($conjurAccount) | |
$InstallationTargetPath = (GetValueFromConfig -key $InstallationTargetPathParameter) | |
HandleCertificate -componentName 'Conjur' -serverUri "$script:ConjurServerDNS/info" -pemTargetDir $InstallationTargetPath -action 'Installation' -trustCert $trustPVWAAndConjurCert -CertificateAbortedMsg $UserMessages.SynchronizerInstallationCertificateAborted | |
LogMsg -Type Debug -Msg $UserMessages.ConjurLogin | |
$loginResponse = ConjurLogin -baseUri $script:ConjurServerDNS -conjurAccount $encodedConjurAccount | |
LogMsg -Type Debug -Msg $UserMessages.ConjurAuth | |
$authenticationResponse = ConjurAuthenticate -baseUri $script:ConjurServerDNS -conjurAccount $encodedConjurAccount -conjurApiKey $loginResponse | |
$conjurToken = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$authenticationResponse")) | |
SetValueInConfig -key $ConjurTokenKeyParameter -value $conjurToken | |
} | |
# ----------------- Conjur login REST ----------------- | |
# Invoke REST login API to Conjur host | |
# Argument conjurAccount needs to be encoded | |
function ConjurLogin($baseUri, $conjurAccount){ | |
$conjurUser = (GetValueFromConfig -key $ConjurAuthenUserKeyParameter) | |
$conjurSecret = (GetValueFromConfig -key $ConjurAuthenApiKeyParameter) | |
$basicCreds = Get-BasicAuthCreds -user $conjurUser -secret $conjurSecret | |
$conjurLoginUri = "$baseUri/authn/$conjurAccount/login" | |
try{ | |
return Invoke-RestMethod @proxyConfig -Uri $conjurLoginUri -Headers @{"Authorization"="Basic $basicCreds"; "UserAgent"="Powershell"} | |
} | |
catch{ | |
$CouldNotLoginToConjurMessage = [string]::Format($UserMessages.CouldNotLoginToConjur, $_.Exception) | |
throw $CouldNotLoginToConjurMessage | |
} | |
} | |
# ----------------- Conjur authenticate REST ----------------- | |
# Invoke REST authenticate API to Conjur host | |
# Argument conjurAccount needs to be encoded | |
function ConjurAuthenticate($baseUri, $conjurAccount, $conjurApiKey){ | |
$encodedconjurUser = [System.Web.HttpUtility]::UrlEncode((GetValueFromConfig -key $ConjurAuthenUserKeyParameter)) | |
$conjurAuthenticateUri = "$baseUri/authn/$conjurAccount/$encodedconjurUser/authenticate" | |
try{ | |
$authenticateResponse = Invoke-RestMethod @proxyConfig -Method Post -Uri $conjurAuthenticateUri -Body $conjurApiKey -UserAgent "Powershell" | |
} | |
catch{ | |
$CouldNotAuthenticateToConjurMessage = [string]::Format($UserMessages.CouldNotAuthenticateToConjur, $_.ErrorDetails) | |
throw $CouldNotAuthenticateToConjurMessage | |
} | |
return ($authenticateResponse | ConvertTo-Json -Compress) | |
} | |
# ----------------- Conjur Cloud start authentication REST ----------------- | |
# Invoke REST start authentication API request to Conjur Cloud | |
function ConjurCloudStartAuthentication($identityTenantBaseUrl, $identityUsername){ | |
$startAuthenticationUrl = "$identityTenantBaseUrl/Security/StartAuthentication" | |
$startAuthenticationBody = ConvertTo-Json @{ | |
Version = "1.0" | |
User = "$identityUsername" | |
} | |
try{ | |
return Invoke-RestMethod @proxyConfig -Uri $startAuthenticationUrl -Headers @{"UserAgent"="Powershell"; "Accept"="*/*"} -Body $startAuthenticationBody -Method Post | |
} | |
catch{ | |
$FailedToAuthenticateToConjurMessage = [string]::Format($UserMessages.FailedToAuthenticateToConjur, $_.Exception) | |
throw $CouldNotAuthenticateToConjurMessage | |
} | |
} | |
# ----------------- Conjur Cloud advance authentication REST ----------------- | |
# Invoke REST advance authentication API request to Conjur Cloud | |
function ConjurCloudAdvanceAuthentication($identityTenantBaseUrl, $sessionId, $mechanismId, [Security.SecureString]$identityPassword){ | |
$identityPasswordPlainText = ConvertSecurePasswordToPlainText -securePassword $identityPassword | |
$advanceAuthenticationUrl = "$identityTenantBaseUrl/Security/AdvanceAuthentication" | |
$advanceAuthenticationBody = ConvertTo-Json @{ | |
Action = "Answer" | |
SessionId = "$sessionId" | |
MechanismId = "$mechanismId" | |
Answer = "$identityPasswordPlainText" | |
} | |
try{ | |
return Invoke-RestMethod @proxyConfig -Uri $advanceAuthenticationUrl -Headers @{"UserAgent"="Powershell"; "Accept"="*/*"} -Body $advanceAuthenticationBody -Method Post | |
} | |
catch{ | |
$FailedToAuthenticateToConjurMessage = [string]::Format($UserMessages.FailedToAuthenticateToConjur, $_.Exception) | |
throw $FailedToAuthenticateToConjurMessage | |
} | |
} | |
# ----------------- Conjur cloud start authentication REST ----------------- | |
# Invoke REST start authentication API request to Conjur cloud | |
function ConjurCloudAuthenticateUser($conjurCloudBaseUrl, $identityToken){ | |
$conjurCloudAuthUrl = "$conjurCloudBaseUrl/api/authn-oidc/cyberark/conjur/authenticate" | |
$conjurCloudAuthBody = @{ | |
id_token = "$identityToken" | |
} | |
try{ | |
return Invoke-RestMethod @proxyConfig -Uri $conjurCloudAuthUrl -Headers @{"UserAgent"="Powershell"; "Accept-Encoding"="base64"} -Body $conjurCloudAuthBody -Method Post | |
} | |
catch{ | |
$CouldNotAuthenticateToConjurMessage = [string]::Format($UserMessages.CouldNotAuthenticateToConjur, $_.Exception) | |
throw $CouldNotAuthenticateToConjurMessage | |
} | |
} | |
# ----------------- Init Conjur Cloud ----------------- | |
# Initialize Conjur by sending authentication REST requests to the prompted hostnamecoaxil | |
function InitConjurCloud(){ | |
LogMsg -Msg $UserMessages.ConjurAuthentication -newLine | |
$script:conjurAccount = "conjur" | |
LogMsg -Msg $UserMessages.ConjurCloudDefaultAccountName -newLine | |
if($silent -eq $false){ | |
$conjurCloudUrl = (ReadHost $UserMessages.ConjurCloudUrlSpecify).TrimEnd('/') | |
SetValueInConfig -key $ConjurServerDNSParameter -value $conjurCloudUrl | |
SetValueInConfig -key $ConjurAccountKeyParameter -value $conjurAccount | |
$script:ConjurServerDNS = $conjurCloudUrl; | |
} | |
} | |
# ----------------- Update Vault.ini ----------------- | |
# notice address should contain no quotes to support DR | |
function UpdateVaultIni($filePath, $vaultName, $VaultAddress, $vaultPort){ | |
$fileContent = (Get-Content -path $filePath) | |
$fileContent = $fileContent -replace "VAULT\s?=\s?`"?[\s\S]*`"?", "VAULT=`"$vaultName`"" | |
$fileContent = $fileContent -replace "ADDRESS\s?=\s?`"?[\s\S]*`"?", "ADDRESS=$VaultAddress" | |
$fileContent = $fileContent -replace "PORT\s?=\s?`"?[\s\S]*`"?", "PORT=`"$vaultPort`"" | |
$fileContent | Set-Content $filePath | |
} | |
# ----------------- Update Config file ----------------- | |
function UpdateConfigFile($filePath, $Items){ | |
$UpdatingFileMessage = [string]::Format($UserMessages.UpdatingFile, $filePath) | |
LogMsg -Type Debug -Msg $UpdatingFileMessage | |
$parsedValues = @{} | |
$Items = $Items -split ", " | |
$Items | foreach{ | |
$item = $_.split("=") | |
$parsedValues.Add($item[0], $item[1]) | |
} | |
$xml = [xml](Get-Content $filePath) | |
foreach ($elem in $xml.configuration.appSettings.ChildNodes){ | |
if($elem.key){ | |
if($parsedValues.ContainsKey($elem.key)){ | |
$UpdatingFileValueOfToMessage = [string]::Format($UserMessages.UpdatingFileValueOfTo, $($elem.key), $($parsedValues[$elem.key])) | |
LogMsg -Type Debug -Msg $UpdatingFileValueOfToMessage | |
$elem.value = $parsedValues[$elem.key] | |
} | |
} | |
} | |
$xml.Save($filePath) | |
} | |
function UpdateTargetInstallationFolderPermissions(){ | |
$InstallationTargetPath = (GetValueFromConfig -key $InstallationTargetPathParameter) | |
$SettingAccessPermissionToFolderMessage = [string]::Format($UserMessages.SettingAccessPermissionToFolder, $InstallationTargetPath) | |
LogMsg -Type Debug -Msg $SettingAccessPermissionToFolderMessage | |
### set Synchronizer Installation folder ACL ### | |
# retrieve ACL (Access Control List) of Installation target folder | |
$Acl = Get-Acl $InstallationTargetPath | |
# protect the access rules associated with this ObjectSecurity object from inheritance (=True) & Don't preserve inherited access rules (=False) | |
$Acl.SetAccessRuleProtection($True , $False) | |
# Grant �Full Control� permissions to Administrators | |
$administratorsSID = New-Object System.Security.Principal.SecurityIdentifier([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $null) | |
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($administratorsSID, "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow") | |
$Acl.SetAccessRule($Ar) | |
# Grant "Read" permissions to Users | |
$usersSID = New-Object System.Security.Principal.SecurityIdentifier([System.Security.Principal.WellKnownSidType]::BuiltinUsersSid, $null) | |
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($usersSID, "Read", "None", "None", "Allow") | |
$Acl.SetAccessRule($Ar) | |
Set-Acl $InstallationTargetPath $Acl | |
} | |
################################################################################################ | |
# Utils | |
################################################################################################ | |
# ----------------- Get Basic authentication credentials ----------------- | |
# Convert given user and secret to compile with basic authorization format | |
function Get-BasicAuthCreds($user, $secret){ | |
$authString = "{0}:{1}" -f $user,$secret | |
$authBytes = [System.Text.Encoding]::Ascii.GetBytes($authString) | |
return [Convert]::ToBase64String($authBytes) | |
} | |
# ----------------- Unzip ----------------- | |
# Unzip a specifed zip file to a specified location, if not exists in the output path | |
function Unzip($zipfile, $outpath){ | |
$UnzippingFileMessage = [string]::Format($UserMessages.UnzippingFile, $zipfile, $outpath) | |
LogMsg -Msg $UnzippingFileMessage | |
if(-not (Test-Path $outpath)){ | |
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) | |
} | |
else{ | |
$DirectoryExistsMessage = [string]::Format($UserMessages.DirectoryExists, $outpath) | |
LogMsg -Msg $DirectoryExistsMessage | |
} | |
} | |
# ----------------- Read config file ----------------- | |
function VerifyMandatoryParam($key){ | |
$value = GetValueFromConfig -key $key | |
if(DoesParameterEmpty($value)){ | |
$MissingMandatoryParamMessage = [string]::Format($UserMessages.MissingMandatoryParam, $key) | |
throw $MissingMandatoryParamMessage | |
} | |
} | |
# ----------------- Read Silent Installation Config File ----------------- | |
function ReadSilentInstallationConfigFile($path){ | |
$SingleQuoteRegex = '^"(.*)"$' | |
$DoubleQuoteRegex = "^'(.*)'$" | |
$fileContent = Get-Content $path | |
foreach ($line in $fileContent){ | |
$values = [regex]::split($line,'=') | |
$keyName = $values[0] | |
$keyValue = $values[1..($values.Length - 1)] -join "=" | |
if(($keyName.CompareTo("") -ne 0) -and (-not $keyName.StartsWith("[")) -and (-not $keyName.StartsWith("#"))){ | |
# Skip empty lines, comments and other non-usable stuff from the silent.ini | |
SetValueInConfig -key $keyName -value ($keyValue -replace $DoubleQuoteRegex,'$1' -replace $SingleQuoteRegex,'$1') | |
} | |
} | |
# Verify all mandatory params | |
VerifyMandatoryParam -key $InstallationTargetPathParameter | |
VerifyMandatoryParam -key $ConjurServerDNSParameter | |
VerifyMandatoryParam -key $VaultNameParameter | |
VerifyMandatoryParam -key $VaultAddressParameter | |
VerifyMandatoryParam -key $VaultPortParameter | |
VerifyMandatoryParam -key $SyncSafeNameParameter | |
if ($false -eq (GetValueFromConfig -key $ConjurCloudSelectedParameter)) { | |
VerifyMandatoryParam -key $ConjurAccountKeyParameter | |
} | |
} | |
function CreateCredFile($credFilePath, $createcredfilePath, $runningExePath, $SynchronizerVaultCredentials){ | |
LogMsg -Msg $UserMessages.VaultCredentails -newLine | |
$createCredFileResponse = & "$createcredfilePath\CreateCredFile.exe" @("`"$credFilePath`"", "Password", "/Username", | |
$SynchronizerVaultCredentials.UserName, "/Password", $SynchronizerVaultCredentials.GetNetworkCredential().Password, "/ExePath", $runningExePath, "/AppType", "AppPrv", | |
"/DPAPIMachineProtection", "/Hostname", "/IPAddress", "/EntropyFile") 2>&1 | |
#"/DPAPIMachineProtection", "/Hostname", "/IPAddress", "/DiskSignature", "/EntropyFile", "/InstallTime", "/MACAddress", "/MachineGUID") 2>&1 | |
if($LASTEXITCODE -ne 0){ | |
throw $createCredFileResponse | |
} | |
} | |
# ----------------- Create PS Credentials ----------------- | |
function CreatePSCredentials([PSCredential] $PSCredentials, $outputPath){ | |
$CreatingCredentialsFileMessage = [string]::Format($UserMessages.CreatingCredentialsFile, $PSCredentials.UserName) | |
LogMsg -Msg $CreatingCredentialsFileMessage -newLine | |
try{ | |
$conjurCredentials = $PSCredentials | |
$conjurCredentials | Export-Clixml -Path $outputPath | |
} | |
finally{ | |
if($conjurCredentials){ | |
$conjurCredentials.Password.Dispose() | |
} | |
} | |
} | |
# ----------------- Copy logs to target installation folder ----------------- | |
function CopyLogs(){ | |
try{ | |
LogMsg -Type Debug -Msg $UserMessages.LogCopy | |
$LogFolderPath = (GetValueFromConfig -key $InstallationTargetPathParameter) + "\Logs" | |
if(-not (Test-Path -Path $LogFolderPath)){ | |
New-Item -ItemType directory -Path $LogFolderPath | Out-Null | |
} | |
# Copy installation log file to target installation folder | |
Copy-Item -Path $LogFilePath -Destination $LogFolderPath -Force -ErrorAction Stop | |
} | |
catch{ | |
$errMsg = $_.Exception.Message | |
$FailedToCopyLogFileMessage = [string]::Format($UserMessages.FailedToCopyLogFile, $errMsg) | |
Write-Error $FailedToCopyLogFileMessage | |
Exit 1 | |
} | |
} | |
# ----------------- Create event log --------------------- | |
function CreateEventLog(){ | |
LogMsg -Msg $UserMessages.EventLog -newLine | |
$SourceExists = [System.Diagnostics.EventLog]::SourceExists("CyberArk Vault-Conjur Synchronizer") | |
if(!$SourceExists){ | |
New-EventLog -LogName "CyberArk Vault-Conjur Synchronizer" -Source "CyberArk Vault-Conjur Synchronizer" | |
Limit-EventLog -LogName "CyberArk Vault-Conjur Synchronizer" -MaximumSize 50MB | |
} | |
else{ | |
LogMsg -Type Debug -Msg $UserMessages.EventLogExist | |
} | |
} | |
# ----------------- Install Service --------------------- | |
function InstallService(){ | |
LogMsg -Msg $UserMessages.SynchronizerInstalling -newLine | |
$serviceName = "CyberArkVaultConjurSynchronizer" | |
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue | |
if(!$service){ | |
$exePath = '"' + [System.IO.Path]::Combine((GetValueFromConfig -key $InstallationTargetPathParameter), "VaultConjurSynchronizer.exe") + '"' | |
$params = @{ | |
Name = $serviceName | |
BinaryPathName = $exePath | |
DisplayName = "CyberArk Vault-Conjur Synchronizer" | |
StartupType = "Automatic" | |
Description = "Synchronizes secrets, stored and managed in the CyberArk Vault, with Conjur." | |
} | |
New-Service @params | |
& sc.exe @("failure",$serviceName,"reset=86400","actions=restart/60000/restart/60000//") | |
if($LASTEXITCODE -ne 0){ | |
throw $UserMessages.VaultConjurSynchronizerServiceInstallationFailed | |
} | |
} | |
else{ | |
LogMsg -Msg $UserMessages.SynchronizerExist -newLine | |
} | |
} | |
function MainPVWAAPIFlow{ | |
param($PVWAURL,[PSCredential] $VaultAdminCredentials, $SyncSafeName,[PSCredential] $SynchronizerVaultCredentials, $credFilePath, $createCredFilePath, $SynchronizerExePath, $ConjurCloudSelected) | |
$script:pvwaModulePath = "$ScriptDir\Modules\PVWAapi.ps1" | |
if(-not $forceNoPVWAApiUse){ | |
$InstallationTargetPath = (GetValueFromConfig -key $InstallationTargetPathParameter) | |
HandleCertificate -componentName 'PVWA' -serverUri "$PVWAURL/passwordvault" -pemTargetDir $InstallationTargetPath -action 'Installation' -trustCert $trustPVWAAndConjurCert | |
Import-Module $pvwaModulePath -Force | |
$pvwaVersion = Init $LogFilePath $silent $PVWAURL $VaultAdminCredentials $SyncSafeName $ScriptDir | |
$script:doesPVWAAPIExist = DoesPVWAAPIExist $pvwaVersion | |
if(-not $silent -and -not $doesPVWAAPIExist){ | |
$SynchronizerVaultUserName = ReadHostWithDefaultValue -Message $UserMessages.SynchronizerVaultUserNameSpecify -defaultValue "$SyncPrefix$env:computername" | |
$SynchronizerVaultUserPassword = GetPassword -userPromptMsg $UserMessages.SynchronizerVaultUserPasswordSpecify | |
$SynchronizerVaultCredentials = New-Object System.Management.Automation.PSCredential ($SynchronizerVaultUserName, $SynchronizerVaultUserPassword) | |
CreateCredFile -credfilePath $credFilePath -createcredfilePath $createCredFilePath -runningExePath $SynchronizerExePath -SynchronizerVaultCredentials $SynchronizerVaultCredentials | |
} | |
if($silent){ | |
VerifyMandatoryParam -key $PVWAURLParameter | |
} | |
if($doesPVWAAPIExist){ | |
if ($ConjurCloudSelected -eq $true) { | |
$numberOfAccountsInConjurSyncSafe = GetNumberOfLobAccountsInConjurSyncSafe $SyncSafeName | |
if ($numberOfAccountsInConjurSyncSafe -gt 1) { | |
LogMsg -Type Error -Msg $UserMessages.TooManyLobAccountsForConjurCloud -newLine | |
exit 1 | |
} | |
} | |
AddUser $SynchronizerVaultCredentials $credFilePath $createCredFilePath $SynchronizerExePath | |
AddSynchronizerVaultUserToPVWAConfigSafe $SynchronizerVaultCredentials.UserName | |
CreateConjurSyncSafe | |
AddSynchronizerVaultUserToSyncSafe $SynchronizerVaultCredentials.UserName | |
AddVaultAdminsGroupToSyncSafe | |
HandleConjurHostPlatform $SynchronizerVaultCredentials.UserName | |
if((GetValueFromConfig -key $MultiNodeEnabledParameter) -eq $true){ | |
HandleConjurDatabasePlatform | |
} | |
} | |
} | |
elseif(-not $silent){ | |
$script:doesPVWAAPIExist = $false | |
$SynchronizerVaultUserName = ReadHostWithDefaultValue -Message $UserMessages.SynchronizerVaultUserNameSpecify -defaultValue "$SyncPrefix$env:computername" | |
$SynchronizerVaultUserPassword = GetPassword -userPromptMsg $UserMessages.SynchronizerVaultUserPasswordSpecify | |
$SynchronizerVaultCredentials = New-Object System.Management.Automation.PSCredential ($SynchronizerVaultUserName, $SynchronizerVaultUserPassword) | |
CreateCredFile -credfilePath $credFilePath -createcredfilePath $createCredFilePath -runningExePath $SynchronizerExePath -SynchronizerVaultCredentials $SynchronizerVaultCredentials | |
} | |
} | |
function DoesPVWAAPIExist { | |
param($versionNumber) | |
if($versionNumber -ge 11.4){ | |
return $true | |
} | |
else{ | |
return $false | |
} | |
} | |
function PVWACreateConjurAccount{ | |
param($ConjurServerDNS, $ConjurAccount, $SynchronizerVaultUserName) | |
if(-not $forceNoPVWAApiUse){ | |
Import-Module $pvwaModulePath -Force | |
if($doesPVWAAPIExist){ | |
HandleConjurHostAccount $Script:objectApiKey $ConjurServerDNS $ConjurAccount $SynchronizerVaultUserName | |
} | |
} | |
} | |
function PVWACreateConjurDatabaseAccount{ | |
if(-not $forceNoPVWAApiUse){ | |
Import-Module $pvwaModulePath -Force | |
if($doesPVWAAPIExist){ | |
HandleConjurDatabaseAccount -databaseUsername $Script:ConjurDatabaseUsername -databaseKey $script:ConjurDatabasePassword -databaseHost $script:ConjurDatabaseHost -databasePort $script:ConjurDatabasePort | |
} | |
} | |
} | |
function PVWACreateLOB{ | |
param($VaultAddress, $ConjurCloudSelected, $ConjurSyncSafeName) | |
if(-not $forceNoPVWAApiUse){ | |
Import-Module $pvwaModulePath -Force | |
if($doesPVWAAPIExist){ | |
if ($ConjurCloudSelected -eq $true){ | |
$lobAccountsCountInConjurSyncSafe = GetNumberOfLobAccountsInConjurSyncSafe $ConjurSyncSafeName | |
if ($lobAccountsCountInConjurSyncSafe -gt 0) { | |
LogMsg -Msg $UserMessages.LOBAccountExistsForConjurCloud -newLine | |
return | |
} | |
} | |
if($silent){ | |
try { | |
VerifyMandatoryParam -key $LOBNameParameter | |
} catch { | |
LogMsg -Msg $UserMessages.LOBNameEmpty -newLine | |
return | |
} | |
$LobName = (GetValueFromConfig -key $LOBNameParameter) | |
$script:LOBPlatformName = (GetValueFromConfig -key $LOBPlatformParameter) | |
if ([string]::IsNullOrEmpty($script:LOBPlatformName)) { | |
$script:LOBPlatformName = $LOBDefaultPlatform | |
$UsingDefaultLobPlatformMessage = [string]::Format($UserMessages.DefaultLOBPlatform, $script:LOBPlatformName) | |
LogMsg -Msg $UsingDefaultLobPlatformMessage -newLine | |
} | |
} | |
else{ | |
$createLob = ReadHost -Message $UserMessages.DefineLOBSpecify | |
if ('yes' -ne $createLob) { | |
return | |
} | |
$LOBName = '' | |
if ($ConjurCloudSelected -eq $true){ | |
#We can read only one LOB and doesn't have to verify if it already exist, since we already did that. | |
$LOBName = ReadHostWithDefaultValue -Message $UserMessages.LOBNameSpecify -defaultValue $ConjurCloudDefaultLob | |
} else { | |
$LOBName = ReadLobNameFromConsole -defaultValue $defaultLob | |
} | |
$script:LOBPlatformName = ReadHostWithDefaultValue -Message $UserMessages.LOBPlatformSpecify -defaultValue $LOBDefaultPlatform | |
} | |
AddLOB $VaultAddress $LOBPlatformName $LobName | |
} | |
} | |
} | |
function GetNumberOfLobAccountsInConjurSyncSafe { | |
param($ConjurSyncSafeName) | |
$FilterOnConjurSyncSafe = "filter=safeName eq $ConjurSyncSafeName" | |
$content = $(Invoke-AccountGetAllBySafeFailoverRequest $FilterOnConjurSyncSafe) | |
$jsonContent = ConvertFrom-Json -InputObject $content | |
$lobAccountsInSafe = $jsonContent.value | Where-Object { $_.name -like $LobAccountPrefix + "*" } | |
$accountsCount = 0 | |
$lobAccountsInSafe | ForEach-Object {$accountsCount++}; | |
return $accountsCount | |
} | |
function PVWACreateLOBs{ | |
param($PVWAURL, $VaultAddress,[PSCredential] $VaultAdminCredentials, $SyncSafeName, $LOBPlatformName, $LobNames) | |
if(-not $forceNoPVWAApiUse){ | |
if($doesPVWAAPIExist -and -not $silent){ | |
$answer = ReadHost -Message $UserMessages.DefineLOBsSpecify -defaultValue "no" | |
if('yes' -eq $answer){ | |
$generateLOBsPath = "$ScriptDir\GenerateLOBs.ps1" | |
VerifyScriptModuleCertificate $scriptPath $generateLOBsPath | |
Import-Module $generateLOBsPath -ArgumentList $PVWAURL,$VaultAddress,$VaultAdminCredentials.UserName,$VaultAdminCredentials.GetNetworkCredential().Password,$SyncSafeName,$LOBPlatformName,$LobNames,$true,$trustPVWAAndConjurCert -Force | |
} | |
} | |
} | |
} | |
function PVWALogouot{ | |
if(-not $forceNoPVWAApiUse){ | |
Import-Module $pvwaModulePath -Force | |
Logout | |
} | |
} | |
function DeleteConjurHostInVault { | |
param($newHostName) | |
if(-not $forceNoPVWAApiUse){ | |
Import-Module $pvwaModulePath -Force | |
if($doesPVWAAPIExist){ | |
RemoveConjurHostAccount $newHostName | |
} | |
} | |
} | |
function ConjurGroupExists { | |
param($groupUri, $conjurToken) | |
try{ | |
Invoke-RestMethod @proxyConfig -Uri $groupUri -Headers @{"Authorization"="Token token=`"$conjurToken`""; "UserAgent"="Powershell"} | |
return $true; | |
} | |
catch{ | |
return $false | |
} | |
} | |
function GetBaseUriForConjurApi { | |
param($parameterName) | |
$baseUri = (GetValueFromConfig -key $parameterName) | |
if ($true -eq (GetValueFromConfig -key $ConjurCloudSelectedParameter)){ | |
$baseUri = "$baseUri/api" | |
} | |
return $baseUri | |
} | |
function MultiNodeSetupConfiguration { | |
# Multi-Node | |
if(-not $silent){ | |
$multinodeEnabled = ReadHost -Message $UserMessages.DefineSynchronizerModeSpecify | |
if ('yes' -eq $multinodeEnabled) | |
{ | |
SetValueInConfig -key $MultiNodeEnabledParameter -value true | |
DO { | |
$clusterKey = ReadHost -Message $UserMessages.ClusterKeySpecify | |
} while (-not $clusterKey) | |
} else { | |
SetValueInConfig -key $MultiNodeEnabledParameter -value false | |
$clusterKey = ReadHostWithDefaultValue -Message $UserMessages.InstanceNameSpecify -defaultValue "${env:computername}" | |
} | |
SetValueInConfig -key $ClusterKeyParameter -value $clusterKey | |
} | |
else { | |
VerifyMandatoryParam -key $MultiNodeEnabledParameter | |
$multiNodeEnabled = GetValueFromConfig -key $MultiNodeEnabledParameter | |
if ($multiNodeEnabled -eq $true) { | |
VerifyMandatoryParam -key $ClusterKeyParameter | |
} else { | |
$clusterKey = GetValueFromConfig -key $ClusterKeyParameter | |
if ([string]::IsNullOrEmpty($clusterKey)) { | |
$computerName = "${env:computername}" | |
ReplaceValueInConfig -key $ClusterKeyParameter -value "${computerName}" | |
} | |
} | |
} | |
} | |
#endregion | |
################################################################################################ | |
# Main script | |
################################################################################################ | |
#region [Main] | |
try{ | |
foreach ($spType in [System.Enum]::GetValues([System.Net.SecurityProtocolType])){ | |
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor $spType | |
} | |
# Get location of script | |
$ScriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent | |
# Initialize log location | |
$LogFilePath = "$ScriptDir\Installation.log" | |
VerifyScriptsSignature -ScriptDir $ScriptDir | |
$script:scriptPath = "$ScriptDir\V5SynchronizerInstallation.ps1" | |
$SynchronizerBaseModulePath = "$ScriptDir\Modules\SynchronizerBase.ps1" | |
Import-Module $SynchronizerBaseModulePath -Force | |
$userMessagesFilePath = "$ScriptDir\UserMessages.psd1" | |
$UserMessages = Import-PowerShellDataFile -Path $userMessagesFilePath | |
WriteWelcome | |
LogMsg -Msg $UserMessages.StartingInstallation -newLine | |
# Enable unzipping and encoding | |
Add-Type -AssemblyName System.IO.Compression.FileSystem | |
Add-Type -AssemblyName System.Web | |
# Ask user if they use a proxy | |
$useProxy = Read-Host "Do you need to use a proxy? (yes/no)" | |
if ($useProxy -match '^(y|yes)$') { | |
# Ask for proxy address | |
$proxyURL = Read-Host "Enter the proxy URL (e.g., http://proxy.company.com:8080)" | |
# Ask if proxy requires authentication | |
$needsAuth = Read-Host "Does the proxy require authentication? (yes/no)" | |
if ($needsAuth -match '^(y|yes)$') { | |
$proxyCred = Get-Credential -Message "Enter proxy credentials" | |
$proxyConfig = @{ | |
Proxy = $proxyURL | |
ProxyCredential = $proxyCred | |
} | |
} else { | |
$proxyConfig = @{ | |
Proxy = $proxyURL | |
} | |
} | |
} else { | |
$proxyConfig = @{} | |
} | |
if($silent){ | |
LogMsg -Msg $UserMessages.SynchronizerSilentInstallation | |
ReadSilentInstallationConfigFile "$ScriptDir\silent.ini" | |
} | |
# Conjur Cloud | |
$conjurCloudSelected = ReadHost -Message $UserMessages.ConjurCloudSelected | |
if('cloud' -eq $conjurCloudSelected){ | |
SetValueInConfig -key $ConjurCloudSelectedParameter -value true | |
# Multi-Node -> false, not supported in Conjur Cloud | |
SetValueInConfig -key $ClusterKeyParameter -value "" | |
SetValueInConfig -key $MultiNodeEnabledParameter -value false | |
} | |
else{ | |
SetValueInConfig -key $ConjurCloudSelectedParameter -value false | |
MultiNodeSetupConfiguration | |
} | |
SetValueInConfig -key $InstallationTargetPathParameter -value (ReadHostWithDefaultValue -Message $UserMessages.InstallationPathSpecify -defaultValue "${env:ProgramFiles}\CyberArk\Synchronizer") | |
$InstallationTargetPath = (GetValueFromConfig -key $InstallationTargetPathParameter) | |
if(-not (Test-Path -Path $InstallationTargetPath)){ | |
Copy-Item -Path "$ScriptDir\..\VaultConjurSynchronizer" -Destination $InstallationTargetPath -Recurse -Force -ErrorAction Stop | |
} | |
else{ | |
$DirectoryExistsMessage = [string]::Format($UserMessages.DirectoryExists, $InstallationTargetPath) | |
LogMsg -Type Debug -Msg $DirectoryExistsMessage | |
} | |
# Update VaultConjurSynchronizer.exe.config | |
$multinodeEnabled=GetValueFromConfig($MultiNodeEnabledParameter) | |
$clusterKey=GetValueFromConfig($ClusterKeyParameter) | |
$itemsToUpdate = "SYNCHRONIZER_MULTI_NODE_ENABLED=$multinodeEnabled", "SYNCHRONIZER_CLUSTER_KEY=$clusterKey" | |
UpdateConfigFile -filePath ((GetValueFromConfig($InstallationTargetPathParameter)) + "\VaultConjurSynchronizer.exe.config") -Items $itemsToUpdate | |
SetValueInConfig -key $VaultNameParameter -value (ReadHost $UserMessages.VaultNameSpecify) | |
$VaultName = (GetValueFromConfig -key $VaultNameParameter) | |
SetValueInConfig -key $PVWAURLParameter -value (ReadHost $UserMessages.PVWAURLSpecify) | |
$PVWAURL = (GetValueFromConfig -key $PVWAURLParameter) | |
SetValueInConfig -key $VaultAddressParameter -value (ReadHost $UserMessages.VaultAddressSpecify) | |
SetValueInConfig -key $VaultPortParameter -value (ReadHostWithDefaultValue -Message $UserMessages.VaultPortSpecify -defaultValue $UserMessages.VaultDefaultPort) | |
# Edit Vault.ini | |
$vaultFilePath = "$InstallationTargetPath\Vault\Vault.ini" | |
$UpdatingFileMessage = [string]::Format($UserMessages.UpdatingFile, $vaultFilePath) | |
LogMsg -Type Debug -Msg $UpdatingFileMessage | |
$VaultAddress = GetValueFromConfig -key $VaultAddressParameter | |
UpdateVaultIni -filePath $vaultFilePath -vaultName $VaultName -VaultAddress $VaultAddress -vaultPort (GetValueFromConfig -key $VaultPortParameter) | |
$SynchronizerVaultUsername = "$SyncPrefix$env:computername" | |
$SynchronizerVaultUserPassword = GetRandomPassword | |
$SynchronizerVaultCredentials = New-Object System.Management.Automation.PSCredential -ArgumentList $SynchronizerVaultUsername,$SynchronizerVaultUserPassword | |
$credFilePath = "$InstallationTargetPath\Vault\VaultConjurSynchronizerUser.cred" | |
$createCredFilePath = "$ScriptDir\CreateCredFile" | |
$SynchronizerExePath = (GetValueFromConfig -key $InstallationTargetPathParameter) + "\VaultConjurSynchronizer.exe" | |
if($silent){ | |
$script:ConjurServerDNS = (GetValueFromConfig -key $ConjurServerDNSParameter) | |
$script:conjurAccount = (GetValueFromConfig -key $ConjurAccountKeyParameter) | |
} | |
else{ | |
$vaultAdminUserName = ReadHost -Message $UserMessages.LogonUserNameSpecify | |
$vaultAdminPassword = GetPassword -userPromptMsg $UserMessages.LogonPasswordSpecify | |
$VaultAdminCredentials = New-Object System.Management.Automation.PSCredential ($vaultAdminUserName, $vaultAdminPassword) | |
} | |
$conjurCloudSelectedParameterValue = GetValueFromConfig -key $ConjurCloudSelectedParameter | |
if ($conjurCloudSelectedParameterValue -eq $true) { | |
# Conjur Cloud host input is already supposed to have host prefix | |
$script:HostPrefix = "" | |
} | |
SetValueInConfig -key $SyncSafeNameParameter -value (ReadHost $UserMessages.AdminSafeSpecify) | |
$SyncSafeName = (GetValueFromConfig -key $SyncSafeNameParameter) | |
MainPVWAAPIFlow -PVWAURL $PVWAURL -VaultAdminCredentials $VaultAdminCredentials -SyncSafeName $SyncSafeName -SynchronizerVaultCredentials $SynchronizerVaultCredentials -credFilePath $credFilePath -createCredFilePath $createCredFilePath -SynchronizerExePath $SynchronizerExePath -ConjurCloudSelected $conjurCloudSelectedParameterValue | |
UpdateTargetInstallationFolderPermissions | |
if($conjurCloudSelectedParameterValue -eq $true) | |
{ | |
InitConjurCloud | |
} | |
else { | |
InitConjur | |
} | |
# Edit VaultConjurSynchronizer.exe.config (If CONJUR_CLOUD_SELECTED is true, SYNC_ALL_PROPERTIES and CONJUR_API_KEY_ROTATION_ENABLED have to be true, otherwise they can stay false) | |
$itemsToUpdate = "INTEGRATION_VAULT_NAME=$VaultName", "SYNC_SAFE_NAME=$SyncSafeName", "SYNC_ALL_PROPERTIES=$conjurCloudSelectedParameterValue", "CONJUR_CLOUD_SELECTED=$conjurCloudSelectedParameterValue", "CONJUR_API_KEY_ROTATION_ENABLED=$conjurCloudSelectedParameterValue" | |
UpdateConfigFile -filePath ((GetValueFromConfig($InstallationTargetPathParameter)) + "\VaultConjurSynchronizer.exe.config") -Items $itemsToUpdate | |
$clusterName = (GetValueFromConfig -key $ClusterKeyParameter) | |
if($conjurCloudSelectedParameterValue -eq $true) | |
{ | |
if($silent){ | |
$ConjurCloudHostnameAndTokenEncodedBase64 = GetValueFromConfig -key $ConjurCloudHostAndTokenParameter | |
} else { | |
$ConjurCloudHostnameAndTokenAsSecuret = ReadHost -Message $UserMessages.ConjurCloudHostnameAndToken -AsSecureString | |
$ConjurCloudHostnameAndTokenEncodedBase64 = ConvertSecurePasswordToPlainText -securePassword $ConjurCloudHostnameAndTokenAsSecuret | |
} | |
$ConjurCloudHostnameAndToken = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($ConjurCloudHostnameAndTokenEncodedBase64)) | |
$ConjurCloudHostnameAndTokenSplit = $ConjurCloudHostnameAndToken.Split(":") | |
$ConjurCloudHostname = $ConjurCloudHostnameAndTokenSplit[0] | |
$ConjurHostName = $ConjurCloudHostname | |
$ConjurCloudToken = $ConjurCloudHostnameAndTokenSplit[1] | |
ReplaceValueInConfig -key $ConjurTokenKeyParameter -value $ConjurCloudToken | |
# Remove old conjur host account from vault | |
DeleteConjurHostInVault $ConjurCloudHostname | |
# In Conjur Cloud Host is built-in so we don't have to do anything with it besides rotating the API key | |
RotateConjurCloudApiKey -conjurHostId $ConjurCloudHostname -conjurHostFileOutputPath "$ScriptDir\synchronizerConjurHost.xml" | |
} | |
else | |
{ | |
$ConjurHostName = "$SyncPrefix$clusterName" | |
# Remove old conjur host account from vault | |
DeleteConjurHostInVault $ConjurHostName | |
# Create the Synchronizer Conjur host and policy | |
CreateConjurHostAndPolicy -conjurHostId $ConjurHostName -conjurHostCredFileOutputPath "$ScriptDir\synchronizerConjurHost.xml" -vaultName $VaultName | |
} | |
PVWACreateConjurAccount -ConjurServerDNS $script:ConjurServerDNS -ConjurAccount $script:conjurAccount -SynchronizerVaultUserName "$script:HostPrefix$ConjurHostName" | |
# Create Conjur Database configuration in vault | |
if((GetValueFromConfig -key $MultiNodeEnabledParameter) -eq $true){ | |
if($conjurCloudSelectedParameterValue -eq $true) | |
{ | |
# This should never happen because multi node is set to false if conjur cloud is selected | |
LogMsg -Type Error -Msg $UserMessages.ConjurCloudMultiNodeNotSupported -newLine | |
exit 1 | |
} | |
else { | |
GetDatabaseConfigurationFromConjur | |
PVWACreateConjurDatabaseAccount | |
} | |
} | |
CreateEventLog | |
InstallService | |
PVWACreateLOB -VaultAddress $VaultAddress -ConjurCloudSelected $conjurCloudSelectedParameterValue -ConjurSyncSafeName $SyncSafeName | |
LogMsg -Msg $UserMessages.SynchronizerInstallationSucceeded -newLine | |
} | |
catch{ | |
$errMsg = $_.Exception.Message | |
# Redirect the Exception to log file | |
$FailedToInstallMessage = [string]::Format($UserMessages.FailedToInstall, $errMsg) | |
LogMsg -Type Error -Msg $FailedToInstallMessage | |
Exit 1 | |
} | |
finally{ | |
try{ | |
PVWALogouot | |
CopyLogs | |
} | |
catch{ } | |
} | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment