WordPress.org

Make WordPress Core

Opened 6 months ago

Last modified 5 weeks ago

#53024 new enhancement

List https functionality health check failures as critical

Reported by: peterwilsoncc Owned by:
Milestone: 5.9 Priority: normal
Severity: normal Version: 5.7
Component: Site Health Keywords: needs-patch needs-codex
Focuses: docs Cc:

Description

In #52783 site health check https failures were reduced to warnings pending some documentation improvements due to false negatives increasing the load on hosting companies' tech support teams.

This follow up ticket is to return the warning level to critical with the following considerations:

  • Fine tune when failures should report warnings or critical errors
  • Improve documentation on WordPress.org to avoid overburdening hosting support teams
  • Link to WordPress.org documentation as a primary call to action rather than contacting the user's host.

Change History (4)

#1 @desrosj
5 months ago

  • Keywords needs-patch added
  • Milestone changed from 5.8 to 5.9

This one still needs a patch. With feature freeze for 5.8 today, it looks like it will need a bit more time.

Pinging @Clorith to make sure this one is on his radar as a maintainer.

#2 @Clorith
5 months ago

  • Keywords needs-codex added

Radar is fired up, this is awaiting dotorg documentation updates still I believe, I've added the keyword for that.

#3 @Clorith
5 weeks ago

I've been looking at the HTTPS validation used for these checks (for the first bullet point, of fine tuning the checks). I wonder if we could change the wp_is_https_supported() function to instead do as @ipstenu suggested in #52783, and make a HTTPS validation check that doesn't rely on finding output generated by WordPress, but instead just does a SSL cert check, and validation, on the URL set as your site URL.

This makes even more sense with headless solutions becoming more likely with recent strides over the last few years, where WordPress doesn't handle the output at all, and as Mika mentions, if you've got issues getting to wp-admin, you'll already have had to cross the hurdle to reach the Site Health checks.

Fetching the certificate it self was fairly straight forward while playing around, but relied on stream_*, and then parsing it using openssl_x509_parse, but I'm not sure how widely available these function are, or if it is something hosts generally disable (perhaps @JavierCasares knows a bit more about this from a host perspective?).
I'm thinking if the function may not exist (it comes with the openssl extension, which is recommended but not required) it may be worthwhile to skip the test as it can't be reliably ran, but this is just thinking out loud.

There are also libraries available for validating SSL (see for example spatie/ssl-certificate as the first result I got when looking into this), but a simple check for "Does the site have a valid certificate" wouldn't need more than a call which then verified the certificate that is returned has the site URL it requested as part of the DNS entries, and that the current time is within the certificate lifespan, so relying on a third party library here might not bring a lot of benefit to the project as a whole. It looks like the Requests library, which we use in core, has some validation functions, but I've not looked into how flexible they are for this kind of scenario.

If the tests are made platform agnostic, then we might not need to expand on the documentation than what already exists at https://wordpress.org/support/article/why-should-i-use-https/ (which is generalised into more of a "what does HTTPS doe for me" format)

cc @flixos90 for thoughts on the HTTPS validation changes, as the one spearheading the efforts there originally.

#4 @JavierCasares
5 weeks ago

Some time ago I tried to have a site to check the certificates for my sites. I used this main function (sorry, some parts in Spanish).

function CertificadoAnalizar($d, $port = 443) {
  $timeout = 1;
  $data = [];
  $almacenar_metadata = [];
  $stream = stream_context_create(array('ssl' => array('capture_peer_cert' => true, 'capture_peer_cert_chain' => true, 'verify_peer' => false, 'peer_name' => $d, 'verify_peer_name' => false, 'allow_self_signed' => true, 'sni_enabled' => true)));
  $read_stream = stream_socket_client('ssl://'.$d.':'.$port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream);
  if($read_stream === false) {
    $data['error'] = [$errstr];
  } else {
    $context = stream_context_get_params($read_stream);
    $almacenar_metadata = stream_get_meta_data($read_stream);
    $chain_data = $context['options']['ssl']['peer_certificate_chain'];
    $chain_length = count($chain_data);
    if (isset($chain_data) && $chain_length < 10) {
      foreach($chain_data as $key => $value) {
        $data['chain'][$key] = $value;
        unset($key, $value);
      }
    } else {
      $data['error'] = ['La cadena es muy larga.'];
    }
  }
  unset($stream, $read_stream, $context, $chain_data, $chain_length);
  $certificatedata = json_encode('');
  $certificate = array();
  if(isset($data['error'])) {
    $certificate['error'] = 1;
    $certificate['errormsg'] = $data['error'];
    $certificate['meta'] = $almacenar_metadata;
    $certificatedata = json_encode($certificate);
    unset($certificate);
  } else {
    $certificate['error'] = 0;
    $certificate['errormsg'] = null;
    $certificate['meta'] = $almacenar_metadata;
    $counter = 0;
    if(count($data['chain']) > 0) {
      foreach($data['chain'] as $chain_key => $chain_value) {
        $cert_data = openssl_x509_parse($chain_value);
        $certificate['cadena'][$counter] = $cert_data;
        $counter++;
      }
      $certificatedata = json_encode($certificate);
    } else {
      $certificate['error'] = 1;
      $certificate['errormsg'] = ['Error procesando el certificado.'];
      $certificatedata = json_encode($certificate);
      unset($certificate);
    }
  }
  unset($data);
  return $certificatedata;
}
$certificado = CertificadoAnalizar($d);
$certificado_data = json_decode($certificado);

With that you can check if a certificate is valid or not. You can also configure if it can be self-signed or not and other things.

For me, the test about "can your site use HTTPS?" is:

  • check if the 443 port is open
  • check if there is a certificate
  • what happens if you try to get the site from the HTTPS (cannot be done? redirection?) In this case, sometimes it will be a good thing and others a bad thing.

So, 5 possibles choices:

  • Everything OK: port 443 open, valid public certificate.
  • Yes certificate, self-signed: port 443 open, certificate self-signed.
  • Yes certificate, expired: port 443 open, certificate expired.
  • No certificate: port 443 open, no certificate (valid, invalid or self-signed).
  • No TCP HTTPS: port 443 close.
  • Show a list of options to do, like:
    • OK, go on -> ACTUAL BUTTON
    • Your certificate is self-signed so, you can change it, but people will receive a notification in their browser. You should get a public validated certificate. -> DOC
    • Your certificate is expired. Please renew it -> DOC.
    • Your hosting allows to have a secure connection but you don't have a certificate. -> DOC
    • Your server does not allow secure connection, please contact your hosting provider. -> DOC

Does this make sense?

Note: See TracTickets for help on using tickets.