359 строки
15 KiB
PowerShell
359 строки
15 KiB
PowerShell
using namespace System
|
|
using namespace System.Net
|
|
using namespace System.net.Sockets
|
|
using namespace System.Collections.Generic
|
|
using namespace System.Diagnostics
|
|
|
|
# PowerShell Container Image Support Start
|
|
|
|
if (!$(Get-Command 'Test-NetConnection' -errorAction SilentlyContinue)) {
|
|
function Test-NetConnection {
|
|
param(
|
|
[Parameter(Position = 0, Mandatory = $true)] $HostName,
|
|
[Parameter(Mandatory = $true)] $Port
|
|
);
|
|
process {
|
|
$client = [TcpClient]::new()
|
|
|
|
try {
|
|
$client.Connect($HostName, $Port)
|
|
$result = @{TcpTestSucceeded = $true; InterfaceAlias = 'Unsupported' }
|
|
}
|
|
catch {
|
|
$result = @{TcpTestSucceeded = $false; InterfaceAlias = 'Unsupported' }
|
|
}
|
|
|
|
$client.Dispose()
|
|
return $result
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$(Get-Command 'Resolve-DnsName' -errorAction SilentlyContinue)) {
|
|
function Resolve-DnsName {
|
|
param(
|
|
[Parameter(Position = 0)] $Name,
|
|
[Parameter()] $Server,
|
|
[switch] $CacheOnly,
|
|
[switch] $DnsOnly,
|
|
[switch] $NoHostsFile
|
|
);
|
|
process {
|
|
# ToDo: Add support
|
|
Write-Host "WARNING: Current environment doesn't support multiple DNS sources."
|
|
return @{ IPAddress = [Dns]::GetHostAddresses($Name).IPAddressToString };
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$(Get-Command 'Get-NetAdapter' -errorAction SilentlyContinue)) {
|
|
function Get-NetAdapter {
|
|
param(
|
|
[Parameter(Position = 0, Mandatory = $true)] $HostName,
|
|
[Parameter(Mandatory = $true)] $Port
|
|
);
|
|
process {
|
|
Write-Host 'Unsupported'
|
|
}
|
|
}
|
|
}
|
|
|
|
# PowerShell Container Image Support End
|
|
|
|
function PrintAverageConnectionTime($addressList, $port) {
|
|
Write-Host 'Printing average connection times for 5 connection attempts:' -ForegroundColor Green
|
|
$stopwatch = [StopWatch]::new()
|
|
|
|
foreach ($ipAddress in $addressList) {
|
|
[double]$sum = 0
|
|
[int]$numFailed = 0
|
|
[int]$numSuccessful = 0
|
|
|
|
for ($i = 0; $i -lt 5; $i++) {
|
|
$client = [TcpClient]::new()
|
|
try {
|
|
$stopwatch.Restart()
|
|
$client.Connect($ipAddress, $port)
|
|
$stopwatch.Stop()
|
|
|
|
$sum += $stopwatch.ElapsedMilliseconds
|
|
|
|
$numSuccessful++
|
|
}
|
|
catch {
|
|
$numFailed++
|
|
}
|
|
$client.Dispose()
|
|
}
|
|
|
|
$avg = 0
|
|
if ($numSuccessful -ne 0) {
|
|
$avg = $sum / $numSuccessful
|
|
}
|
|
|
|
Write-Host ' IP Address:'$ipAddress' Port:'$port
|
|
Write-Host ' Successful connections:'$numSuccessful
|
|
Write-Host ' Failed connections:'$numFailed
|
|
Write-Host ' Average response time:'$avg' ms'
|
|
}
|
|
}
|
|
|
|
function PrintDNSResults($dnsResult, [string] $dnsSource) {
|
|
if ($dnsResult) {
|
|
Write-Host ' Found DNS record in' $dnsSource '(IP Address:'$dnsResult.IPAddress')'
|
|
}
|
|
else {
|
|
Write-Host ' Could not find DNS record in' $dnsSource
|
|
}
|
|
}
|
|
|
|
function ValidateDNS([String] $Server) {
|
|
Try {
|
|
Write-Host 'Validating DNS record for' $Server -ForegroundColor Green
|
|
|
|
if (!$(Get-Command 'Resolve-DnsName' -errorAction SilentlyContinue)) {
|
|
Write-Host " WARNING: Current environment doesn't support multiple DNS sources."
|
|
Write-Host ' DNS resolution:' ([Dns]::GetHostAddresses($Name).IPAddressToString)
|
|
}
|
|
else {
|
|
Try {
|
|
$DNSfromHosts = Resolve-DnsName -Name $Server -CacheOnly -ErrorAction SilentlyContinue
|
|
PrintDNSResults $DNSfromHosts 'hosts file'
|
|
}
|
|
Catch {
|
|
Write-Host "Error at ValidateDNS from hosts file" -Foreground Red
|
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
TrackWarningAnonymously 'Error at ValidateDNS from hosts file'
|
|
}
|
|
|
|
Try {
|
|
$DNSfromCache = Resolve-DnsName -Name $Server -NoHostsFile -CacheOnly -ErrorAction SilentlyContinue
|
|
PrintDNSResults $DNSfromCache 'cache'
|
|
}
|
|
Catch {
|
|
Write-Host "Error at ValidateDNS from cache" -Foreground Red
|
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
TrackWarningAnonymously 'Error at ValidateDNS from cache'
|
|
}
|
|
|
|
Try {
|
|
$DNSfromCustomerServer = Resolve-DnsName -Name $Server -DnsOnly -ErrorAction SilentlyContinue
|
|
PrintDNSResults $DNSfromCustomerServer 'DNS server'
|
|
}
|
|
Catch {
|
|
Write-Host "Error at ValidateDNS from DNS server" -Foreground Red
|
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
TrackWarningAnonymously 'Error at ValidateDNS from DNS server'
|
|
}
|
|
|
|
Try {
|
|
$DNSfromOpenDNS = Resolve-DnsName -Name $Server -DnsOnly -Server 208.67.222.222 -ErrorAction SilentlyContinue
|
|
PrintDNSResults $DNSfromOpenDNS 'Open DNS'
|
|
}
|
|
Catch {
|
|
Write-Host "Error at ValidateDNS from Open DNS" -Foreground Red
|
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
TrackWarningAnonymously 'Error at ValidateDNS from Open DNS'
|
|
}
|
|
}
|
|
}
|
|
Catch {
|
|
Write-Host "Error at ValidateDNS" -Foreground Red
|
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
}
|
|
}
|
|
|
|
function TrackWarningAnonymously ([String] $warningCode) {
|
|
Try {
|
|
if ($SendAnonymousUsageData) {
|
|
$body = New-Object PSObject `
|
|
| Add-Member -PassThru NoteProperty name 'Microsoft.ApplicationInsights.Event' `
|
|
| Add-Member -PassThru NoteProperty time $([System.dateTime]::UtcNow.ToString('o')) `
|
|
| Add-Member -PassThru NoteProperty iKey "a75c333b-14cb-4906-aab1-036b31f0ce8a" `
|
|
| Add-Member -PassThru NoteProperty tags (New-Object PSObject | Add-Member -PassThru NoteProperty 'ai.user.id' $AnonymousRunId) `
|
|
| Add-Member -PassThru NoteProperty data (New-Object PSObject `
|
|
| Add-Member -PassThru NoteProperty baseType 'EventData' `
|
|
| Add-Member -PassThru NoteProperty baseData (New-Object PSObject `
|
|
| Add-Member -PassThru NoteProperty ver 2 `
|
|
| Add-Member -PassThru NoteProperty name $warningCode));
|
|
$body = $body | ConvertTo-JSON -depth 5;
|
|
Invoke-WebRequest -Uri 'https://dc.services.visualstudio.com/v2/track' -Method 'POST' -UseBasicParsing -body $body > $null
|
|
}
|
|
}
|
|
Catch {
|
|
Write-Host 'TrackWarningAnonymously exception:'
|
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
}
|
|
}
|
|
|
|
$parameters = $args[0]
|
|
$Server = $parameters['Server']
|
|
$Port = $parameters['Port']
|
|
$AuthenticationType = $parameters['AuthenticationType']
|
|
$AuthenticationLibrary = $parameters['AuthenticationLibrary']
|
|
$UserAssignedIdentityClientId = $parameters['UserAssignedIdentityClientId']
|
|
$User = $parameters['User']
|
|
$Password = $parameters['Password']
|
|
$Database = $parameters['Database']
|
|
$EncryptionProtocol = $parameters['EncryptionProtocol']
|
|
$RepositoryBranch = $parameters['RepositoryBranch']
|
|
$Local = $parameters['Local']
|
|
$LocalPath = $parameters['LocalPath']
|
|
$SendAnonymousUsageData = $parameters['SendAnonymousUsageData']
|
|
$AnonymousRunId = $parameters['AnonymousRunId']
|
|
$logsFolderName = $parameters['logsFolderName']
|
|
$outFolderName = $parameters['outFolderName']
|
|
|
|
$ConnectionAttempts = 1
|
|
if ($null -ne $parameters['ConnectionAttempts']) {
|
|
$ConnectionAttempts = $parameters['ConnectionAttempts']
|
|
}
|
|
|
|
$DelayBetweenConnections = 1
|
|
if ($null -ne $parameters['DelayBetweenConnections']) {
|
|
$DelayBetweenConnections = $parameters['DelayBetweenConnections']
|
|
}
|
|
|
|
|
|
if ([string]::IsNullOrEmpty($env:TEMP)) {
|
|
$env:TEMP = '/tmp';
|
|
}
|
|
|
|
try {
|
|
Set-Location -Path $env:TEMP
|
|
Set-Location $logsFolderName
|
|
Set-Location $outFolderName
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
|
|
|
|
$TDSClientPath = Join-Path ((Get-Location).Path) "TDSClient.dll"
|
|
$MicrosoftIdentityClientDll = Join-Path ((Get-Location).Path) "Microsoft.Identity.Client.dll"
|
|
$IdentityModelAbstractions = Join-Path ((Get-Location).Path) "Microsoft.IdentityModel.Abstractions.dll"
|
|
$ActiveDirectoryDll = Join-Path ((Get-Location).Path) "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
|
|
|
|
if ($Local) {
|
|
Copy-Item -Path $($LocalPath + '\netstandard2.0\TDSClient.dll') -Destination $TDSClientPath
|
|
Copy-Item -Path $($LocalPath + '\netstandard2.0\Microsoft.Identity.Client.dll') -Destination $MicrosoftIdentityClientDll
|
|
Copy-Item -Path $($LocalPath + '\netstandard2.0\Microsoft.IdentityModel.Abstractions.dll') -Destination $IdentityModelAbstractions
|
|
Copy-Item -Path $($LocalPath + '\netstandard2.0\Microsoft.IdentityModel.Clients.ActiveDirectory.dll') -Destination $ActiveDirectoryDll
|
|
}
|
|
else {
|
|
Invoke-WebRequest -Uri $('https://github.com/Azure/SQL-Connectivity-Checker/raw/' + $RepositoryBranch + '/netstandard2.0/TDSClient.dll') -OutFile $TDSClientPath -UseBasicParsing
|
|
Invoke-WebRequest -Uri $('https://github.com/Azure/SQL-Connectivity-Checker/raw/' + $RepositoryBranch + '/netstandard2.0/Microsoft.Identity.Client.dll') -OutFile $MicrosoftIdentityClientDll -UseBasicParsing
|
|
Invoke-WebRequest -Uri $('https://github.com/Azure/SQL-Connectivity-Checker/raw/' + $RepositoryBranch + '/netstandard2.0/Microsoft.IdentityModel.Abstractions.dll') -OutFile $IdentityModelAbstractions -UseBasicParsing
|
|
Invoke-WebRequest -Uri $('https://github.com/Azure/SQL-Connectivity-Checker/raw/' + $RepositoryBranch + '/netstandard2.0/Microsoft.IdentityModel.Clients.ActiveDirectory.dll') -OutFile $ActiveDirectoryDll -UseBasicParsing
|
|
}
|
|
|
|
$assembly = [System.IO.File]::ReadAllBytes($TDSClientPath)
|
|
$assembly2 = [System.IO.File]::ReadAllBytes($MicrosoftIdentityClientDll)
|
|
$assembly3 = [System.IO.File]::ReadAllBytes($IdentityModelAbstractions)
|
|
$assembly4 = [System.IO.File]::ReadAllBytes($ActiveDirectoryDll)
|
|
[System.Reflection.Assembly]::Load($assembly) | Out-Null
|
|
[System.Reflection.Assembly]::Load($assembly2) | Out-Null
|
|
[System.Reflection.Assembly]::Load($assembly3) | Out-Null
|
|
[System.Reflection.Assembly]::Load($assembly4) | Out-Null
|
|
|
|
$fullLogPath = Join-Path ((Get-Location).Path) 'AdvancedTests_FullLog.txt'
|
|
$logPath = Join-Path ((Get-Location).Path) 'AdvancedTests_LastRunLog.txt'
|
|
$summaryLogPath = Join-Path ((Get-Location).Path) 'AdvancedTests_SummaryLog.txt'
|
|
$summaryLog = [System.IO.File]::CreateText($summaryLogPath)
|
|
[TDSClient.TDS.Utilities.LoggingUtilities]::SetSummaryLog($summaryLog)
|
|
|
|
try {
|
|
switch ($EncryptionProtocol) {
|
|
'Tls 1.0' {
|
|
$encryption = [System.Security.Authentication.SslProtocols]::Tls
|
|
break
|
|
}
|
|
'Tls 1.1' {
|
|
$encryption = [System.Security.Authentication.SslProtocols]::Tls11
|
|
break
|
|
}
|
|
'Tls 1.2' {
|
|
$encryption = [System.Security.Authentication.SslProtocols]::Tls12
|
|
break
|
|
}
|
|
# Not supported
|
|
#'Tls 1.3' {
|
|
# $encryption = [System.Security.Authentication.SslProtocols]::Tls13
|
|
# break
|
|
#}
|
|
default {
|
|
# Allow the operating system to choose the best protocol to use
|
|
$encryption = [System.Security.Authentication.SslProtocols]::Tls12 -bor [System.Security.Authentication.SslProtocols]::Tls11 -bor [System.Security.Authentication.SslProtocols]::Default
|
|
}
|
|
}
|
|
$tdsClient = [TDSClient.TDS.Client.TDSSQLTestClient]::new($Server, $Port, $AuthenticationType, $User, $Password, $Database, $encryption, $AuthenticationLibrary, $UserAssignedIdentityClientId)
|
|
|
|
for ($i = 1; $i -le $ConnectionAttempts; ++$i) {
|
|
$log = [System.IO.File]::CreateText($logPath)
|
|
[TDSClient.TDS.Utilities.LoggingUtilities]::SetVerboseLog($log)
|
|
|
|
$result = $tdsClient.Connect().GetAwaiter().GetResult()
|
|
Write-Host
|
|
$tdsClient.Disconnect()
|
|
|
|
$log.Close()
|
|
[TDSClient.TDS.Utilities.LoggingUtilities]::ClearVerboseLog()
|
|
$result = $([System.IO.File]::ReadAllText($logPath))
|
|
Write-Host $result
|
|
Add-Content -Path $fullLogPath -Value $result
|
|
|
|
# if ($i -lt $ConnectionAttempts) {
|
|
# Write-Host ('Waiting ' + $DelayBetweenConnections + ' second(s)...')
|
|
# Start-Sleep -Seconds $DelayBetweenConnections
|
|
# }
|
|
}
|
|
TrackWarningAnonymously ('Advanced|TDSClient|ConnectAndDisconnect')
|
|
}
|
|
catch {
|
|
[TDSClient.TDS.Utilities.LoggingUtilities]::WriteLog('Failure: ' + $_.Exception.InnerException.Message)
|
|
TrackWarningAnonymously ('Advanced|TDSClient|Exception|' + $_.Exception.InnerException.Message)
|
|
}
|
|
finally {
|
|
$log.Close()
|
|
[TDSClient.TDS.Utilities.LoggingUtilities]::ClearVerboseLog()
|
|
$summaryLog.Close()
|
|
[TDSClient.TDS.Utilities.LoggingUtilities]::ClearSummaryLog()
|
|
Remove-Item $TDSClientPath -Force
|
|
}
|
|
|
|
$result = $([System.IO.File]::ReadAllText($logPath))
|
|
$match = [Regex]::Match($result, "Routing to: (.*)\.")
|
|
if ($match.Success) {
|
|
$array = $match.Groups[1].Value -split ':'
|
|
$server = $array[0]
|
|
$port = $array[1]
|
|
|
|
Write-Host 'Redirect connectivity policy has been detected, running additional tests:' -ForegroundColor Green
|
|
TrackWarningAnonymously 'Advanced|Redirect|Detected'
|
|
|
|
ValidateDNS $server
|
|
|
|
try {
|
|
$dnsResult = [System.Net.DNS]::GetHostEntry($server)
|
|
}
|
|
catch {
|
|
$msg = ' ERROR: Name resolution (DNS) of ' + $server + ' failed'
|
|
Write-Host $msg -Foreground Red
|
|
|
|
$Advanced_DNSResolutionFailed = ' Please make sure the name ' + $server + ' can be resolved (DNS)
|
|
Failure to resolve specific domain names is usually a client-side networking issue that you will need to pursue with your local network administrator.'
|
|
Write-Host $Advanced_DNSResolutionFailed -Foreground Red
|
|
TrackWarningAnonymously 'Advanced|Redirect|DNSResolutionFailedForRedirect'
|
|
return
|
|
}
|
|
|
|
$resolvedAddress = $dnsResult.AddressList[0].IPAddressToString
|
|
Write-Host
|
|
PrintAverageConnectionTime $resolvedAddress $port
|
|
}
|
|
else {
|
|
Write-Host ' Proxy connection policy detected!' -ForegroundColor Green
|
|
TrackWarningAnonymously 'Advanced|Proxy|Detected'
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host 'Running advanced connectivity policy tests failed!' -ForegroundColor Red
|
|
Write-Host $_.Exception
|
|
TrackWarningAnonymously ('Advanced|Exception|' + $_.Exception.Message)
|
|
} |