#Requires -RunAsAdministrator <# .SYNOPSIS Add or remove the Algo VPN .DESCRIPTION Add or remove the Algo VPN See the examples for more information .PARAMETER Add Add the VPN to the local system .PARAMETER Remove Remove the VPN from the local system .PARAMETER GetInstalledCerts Retrieve Algo certs, if any, from the system certificate store .PARAMETER SaveCerts Save the Algo certs embedded in this file .PARAMETER OutputDirectory When saving the Algo certs, save to this directory .PARAMETER Pkcs12DecryptionPassword The decryption password for the user's PKCS12 certificate, sometimes called the "p12 password". Note that this must be passed in as a SecureString, not a regular string. You can create a secure string with the `Read-Host -AsSecureString` cmdlet. See the examples for more information. .PARAMETER AllUsers Allow all users to use the VPN .EXAMPLE client_USER.ps1 -Add Adds the Algo VPN .EXAMPLE $p12pass = Read-Host -AsSecureString; client_USER.ps1 -Add -Pkcs12DecryptionPassword $p12pass Create a variable containing the PKCS12 decryption password, then use it when adding the VPN. This can be especially useful when troubleshooting, because you can use the same variable with multiple calls to client_USER.ps1, rather than having to type the PKCS12 password each time. .EXAMPLE client_USER.ps1 -Remove Removes the Algo VPN if installed. .EXAMPLE client_USER.ps1 -GetIntalledCerts Show the Algo VPN's installed certificates, if any. .EXAMPLE client_USER.ps1 -SaveCerts -OutputDirectory $Home\Downloads Save the embedded CA cert and encrypted user PKCS12 file. #> [CmdletBinding(DefaultParameterSetName="Add")] Param( [Parameter(ParameterSetName="Add")] [Switch] $Add, [Parameter(ParameterSetName="Add")] [SecureString] $Pkcs12DecryptionPassword, [Parameter(ParameterSetName="Add")] [Switch] $AllUsers = $false, [Parameter(Mandatory, ParameterSetName="Remove")] [Switch] $Remove, [Parameter(Mandatory, ParameterSetName="GetInstalledCerts")] [Switch] $GetInstalledCerts, [Parameter(Mandatory, ParameterSetName="SaveCerts")] [Switch] $SaveCerts, [Parameter(ParameterSetName="SaveCerts")] [string] $OutputDirectory = "$PWD" ) $ErrorActionPreference = "Stop" $VpnServerAddress = "{{ IP_subject_alt_name }}" $VpnName = "Algo VPN {{ IP_subject_alt_name }} IKEv2" $VpnUser = "{{ item.0 }}" $CaCertificateBase64 = "{{ PayloadContentCA }}" $UserPkcs12Base64 = "{{ item.1.stdout }}" if ($PsCmdlet.ParameterSetName -eq "Add" -and -not $Pkcs12DecryptionPassword) { $Pkcs12DecryptionPassword = ConvertTo-SecureString '{{ p12_export_password }}' -asplaintext -force } <# .SYNOPSIS Create a temporary directory #> function New-TemporaryDirectory { [CmdletBinding()] Param() do { $guid = New-Guid | Select-Object -ExpandProperty Guid $newTempDirPath = Join-Path -Path $env:TEMP -ChildPath $guid } while (Test-Path -Path $newTempDirPath) New-Item -ItemType Directory -Path $newTempDirPath } <# .SYNOPSIS Retrieve any installed Algo VPN certificates #> function Get-InstalledAlgoVpnCertificates { [CmdletBinding()] Param() Get-ChildItem -LiteralPath Cert:\LocalMachine\Root | Where-Object { $_.Subject -match "^CN=${VpnServerAddress}$" -and $_.Issuer -match "^CN=${VpnServerAddress}$" } Get-ChildItem -LiteralPath Cert:\LocalMachine\My | Where-Object { $_.Subject -match "^CN=${VpnUser}$" -and $_.Issuer -match "^CN=${VpnServerAddress}$" } } function Save-AlgoVpnCertificates { [CmdletBinding()] Param( [String] $OutputDirectory = $PWD ) $caCertPath = Join-Path -Path $OutputDirectory -ChildPath "cacert.pem" $userP12Path = Join-Path -Path $OutputDirectory -ChildPath "$VpnUser.p12" # NOTE: We cannot use ConvertFrom-Base64 here because it is not designed for binary data [IO.File]::WriteAllBytes( $caCertPath, [Convert]::FromBase64String($CaCertificateBase64)) [IO.File]::WriteAllBytes( $userP12Path, [Convert]::FromBase64String($UserPkcs12Base64)) return New-Object -TypeName PSObject -Property @{ CaPem = $caCertPath UserPkcs12 = $userP12Path } } function Add-AlgoVPN { [Cmdletbinding()] Param() $workDir = New-TemporaryDirectory try { $certs = Save-AlgoVpnCertificates -OutputDirectory $workDir $importPfxCertParams = @{ Password = $Pkcs12DecryptionPassword FilePath = $certs.UserPkcs12 CertStoreLocation = "Cert:\LocalMachine\My" } Import-PfxCertificate @importPfxCertParams $importCertParams = @{ FilePath = $certs.CaPem CertStoreLocation = "Cert:\LocalMachine\Root" } Import-Certificate @importCertParams } finally { Remove-Item -Recurse -Force -LiteralPath $workDir } $addVpnParams = @{ Name = $VpnName ServerAddress = $VpnServerAddress TunnelType = "IKEv2" AuthenticationMethod = "MachineCertificate" EncryptionLevel = "Required" AllUserConnection = $AllUsers } Add-VpnConnection @addVpnParams $setVpnParams = @{ ConnectionName = $VpnName AuthenticationTransformConstants = "GCMAES256" CipherTransformConstants = "GCMAES256" EncryptionMethod = "AES256" IntegrityCheckMethod = "SHA384" DHGroup = "ECP384" PfsGroup = "ECP384" Force = $true } Set-VpnConnectionIPsecConfiguration @setVpnParams } function Remove-AlgoVPN { [CmdletBinding()] Param() Get-InstalledAlgoVpnCertificates | Remove-Item -Force Remove-VpnConnection -Name $VpnName -Force } switch ($PsCmdlet.ParameterSetName) { "Add" { Add-AlgoVPN } "Remove" { Remove-AlgoVPN } "GetInstalledCerts" { Get-InstalledAlgoVpnCertificates } "SaveCerts" { $certs = Save-AlgoVpnCertificates -OutputDirectory $OutputDirectory Get-Item -LiteralPath $certs.UserPkcs12, $certs.CaPem } default { throw "Unknown parameter set: '$($PsCmdlet.ParameterSetName)'" } }