简体   繁体   中英

Trusting certificate of HTTPS site in web request

I want to test if our web server (located on the intranet) is online ( 1 ) or offline ( 0 ) from the server containing it using PowerShell 2.0. For this I have a script that navigates to the page and check if a html-string is available on the page.

function Get-HeartBeat {
    $isAlive = $false

    try {
        $webclient = New-Object WebClient

        $userName = "xxx"
        $password = "xxx"
        $domain = "xxx"

        $url  = "ourUrl.com"
        $html = '<input type="submit">'

        $webclient.Credentials = New-Object System.Net.NetworkCredential($userName, $password, $domain)
        $webpage = $webclient.DownloadString($url)

        $isAlive = $webpage.Contains($html)
    } catch {
        # A WebException is thrown if the status code is anything but 200 (OK)
        Write-Host $_
        $isAlive = $false
    }

    return "$([Int32]$isAlive)"
}

Unfortunately this returns an error:

Exception calling "DownloadString" with "1" argument(s): "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."

A way to trust our certificate is to create a type with a certificate policy as follows (modification of this answer ):

Add-Type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;

    public class TrustOurCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint servicePoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) 
        {
            return certificate.Issuer.Equals("OUR ISSUER")
                && certificate.Subject.Contains("our application");
        }
    }
"@

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustOurCertsPolicy

This still feels a bit "stringly typed" instead of 100% secure.

Is this safe? Is there a better way to create a WebClient that has one certificate accepted? The certificate we should trust is available in cert:LocalMachine\\My .

The correct way to handle certificate errors is to import the certificate chain (root and intermediat CA certificates) of the webserver's certificate into the local certificate store (as Trusted Root CA and Intermediate CA respectively). If the server certificate is self-signed you need to import the server certificate as a Trusted Root CA.

Another option, depending on what you actually need to check, might be to modify your algorithm. For instance, if you really need just a heartbeat (not verify that an actual request returns a specific result) you could simply try to establish a TCP connection to the port:

function Get-HeartBeat {
  $url  = 'ourUrl.com'
  $port = 443

  $clnt = New-Object Net.Sockets.TcpClient
  try {
    $clnt.Connect($url, $port)
    1
  } catch {
    0
  } finally {
    $clnt.Dispose()
  }
}

On more recent Windows versions you could use the Test-NetConnection cmdlet to the same end:

function Get-HeartBeat {
  $url  = 'ourUrl.com'
  $port = 443

  [int](Test-Net-Connection -Computer $url -Port $port -InformationLevel Quiet)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM