124 lines
5.7 KiB
PowerShell
124 lines
5.7 KiB
PowerShell
#Requires -Version 5.1
|
|
#Requires -RunAsAdministrator
|
|
[CmdletBinding(SupportsShouldProcess)]
|
|
param(
|
|
[Parameter(Mandatory)][string]$VpnProfilePackagePath,
|
|
[Parameter(Mandatory)][string]$ClientCertificatePfxPath,
|
|
[securestring]$ClientCertificatePfxPassword,
|
|
[Parameter(Mandatory)][string]$ClientRootCertificatePath,
|
|
[string]$ConnectionName = 'SGU Azure P2S',
|
|
[string[]]$AzureNetworkPrefixes = @('10.77.0.0/16'),
|
|
[ipaddress]$DomainControllerIPv4Address = '10.77.0.4',
|
|
[string]$DomainName = 'lci.lasalle.mx',
|
|
[switch]$Connect
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
foreach ($path in @($VpnProfilePackagePath,$ClientCertificatePfxPath,$ClientRootCertificatePath)) {
|
|
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
|
throw "Required P2S file not found: $path"
|
|
}
|
|
}
|
|
if (-not $ClientCertificatePfxPassword) {
|
|
$ClientCertificatePfxPassword = Read-Host 'Password protecting the P2S client PFX' -AsSecureString
|
|
}
|
|
|
|
$temporaryRoot = Join-Path $env:ProgramData ("SGU\AzureP2S\Import-" + [Guid]::NewGuid().ToString('N'))
|
|
try {
|
|
Expand-Archive -LiteralPath $VpnProfilePackagePath -DestinationPath $temporaryRoot -Force
|
|
$vpnSettingsPath = Get-ChildItem -LiteralPath $temporaryRoot -Recurse -Filter VpnSettings.xml -File |
|
|
Select-Object -First 1 -ExpandProperty FullName
|
|
if (-not $vpnSettingsPath) {
|
|
throw 'The Azure package does not contain Generic\VpnSettings.xml. Generate it with IKEv2 enabled.'
|
|
}
|
|
[xml]$vpnSettings = Get-Content -LiteralPath $vpnSettingsPath -Raw
|
|
$vpnServerNode = $vpnSettings.SelectSingleNode('//*[local-name()="VpnServer"]')
|
|
if (-not $vpnServerNode -or [string]::IsNullOrWhiteSpace($vpnServerNode.InnerText)) {
|
|
throw 'VpnSettings.xml does not contain the Azure VPN gateway FQDN.'
|
|
}
|
|
$vpnServer = $vpnServerNode.InnerText.Trim()
|
|
|
|
$serverRootPath = Get-ChildItem -LiteralPath (Split-Path $vpnSettingsPath -Parent) `
|
|
-Filter VpnServerRoot.cer -File | Select-Object -First 1 -ExpandProperty FullName
|
|
if ($serverRootPath) {
|
|
Import-Certificate -FilePath $serverRootPath -CertStoreLocation Cert:\LocalMachine\Root | Out-Null
|
|
}
|
|
$clientRoot = Import-Certificate -FilePath $ClientRootCertificatePath `
|
|
-CertStoreLocation Cert:\LocalMachine\Root | Select-Object -First 1
|
|
$clientCertificates = @(Import-PfxCertificate -FilePath $ClientCertificatePfxPath `
|
|
-Password $ClientCertificatePfxPassword -CertStoreLocation Cert:\LocalMachine\My)
|
|
$clientCertificate = $clientCertificates |
|
|
Where-Object {
|
|
$_.HasPrivateKey -and
|
|
$_.NotAfter -gt (Get-Date) -and
|
|
@($_.EnhancedKeyUsageList | ForEach-Object ObjectId) -contains '1.3.6.1.5.5.7.3.2'
|
|
} |
|
|
Sort-Object NotAfter -Descending |
|
|
Select-Object -First 1
|
|
if (-not $clientCertificate) {
|
|
throw 'The imported PFX does not contain a valid Client Authentication certificate with a private key.'
|
|
}
|
|
|
|
if ($PSCmdlet.ShouldProcess($ConnectionName, 'Install an all-user IKEv2 Azure P2S connection using a machine certificate')) {
|
|
$existingConnection = Get-VpnConnection -Name $ConnectionName -AllUserConnection `
|
|
-ErrorAction SilentlyContinue
|
|
if ($existingConnection) {
|
|
Remove-VpnConnection -Name $ConnectionName -AllUserConnection -Force
|
|
}
|
|
Add-VpnConnection `
|
|
-Name $ConnectionName `
|
|
-ServerAddress $vpnServer `
|
|
-TunnelType Ikev2 `
|
|
-AuthenticationMethod MachineCertificate `
|
|
-MachineCertificateIssuerFilter $clientRoot `
|
|
-MachineCertificateEKUFilter '1.3.6.1.5.5.7.3.2' `
|
|
-EncryptionLevel Required `
|
|
-SplitTunneling `
|
|
-AllUserConnection `
|
|
-DnsSuffix $DomainName `
|
|
-Force | Out-Null
|
|
foreach ($prefix in $AzureNetworkPrefixes) {
|
|
Add-VpnConnectionRoute -ConnectionName $ConnectionName `
|
|
-DestinationPrefix $prefix -AllUserConnection -PassThru | Out-Null
|
|
}
|
|
|
|
$nrptDisplayName = "SGU Azure P2S DNS - $DomainName"
|
|
Get-DnsClientNrptRule -ErrorAction SilentlyContinue |
|
|
Where-Object DisplayName -eq $nrptDisplayName |
|
|
Remove-DnsClientNrptRule -Force
|
|
Add-DnsClientNrptRule `
|
|
-Namespace ".$DomainName" `
|
|
-NameServers $DomainControllerIPv4Address.IPAddressToString `
|
|
-DisplayName $nrptDisplayName `
|
|
-Comment 'Managed by SGU Azure P2S bootstrap; routes only the AD namespace to the domain controller.' | Out-Null
|
|
}
|
|
|
|
if ($Connect) {
|
|
& "$env:SystemRoot\System32\rasdial.exe" $ConnectionName
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Windows could not connect $ConnectionName. Verify UDP 500/4500 (IKEv2) or use the Azure-generated SSTP profile when the local network blocks IKEv2."
|
|
}
|
|
}
|
|
|
|
$connection = Get-VpnConnection -Name $ConnectionName -AllUserConnection
|
|
[pscustomobject]@{
|
|
ConnectionName = $connection.Name
|
|
ServerAddress = $connection.ServerAddress
|
|
TunnelType = $connection.TunnelType
|
|
AllUserConnection = $true
|
|
AuthenticationMethod = $connection.AuthenticationMethod
|
|
ConnectionStatus = $connection.ConnectionStatus
|
|
ClientCertificateThumbprint = $clientCertificate.Thumbprint
|
|
DomainControllerIPv4Address = $DomainControllerIPv4Address.IPAddressToString
|
|
DomainDnsNamespace = ".$DomainName"
|
|
AzureNetworkPrefixes = $AzureNetworkPrefixes
|
|
AvailableBeforeLogon = $true
|
|
}
|
|
}
|
|
finally {
|
|
$ClientCertificatePfxPassword = $null
|
|
if (Test-Path -LiteralPath $temporaryRoot) {
|
|
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|