• 
      

    Add certificate support for hosting services.

    Review Request #14926 — Created March 18, 2026 and updated

    Information

    Review Board
    release-7.1.x

    Reviewers

    This introduces modern certificate support for all hosting services.
    The work required for this is a bit different than just using a
    cert-populated SSL context for urlopen(), as hosting services
    historically have supported storing approved SSL certificate data as
    part of the HostingServiceAccount. Those were conducted with hostname
    checks turned off. That added a bit of complexity and required a
    migration path.

    Now, when preparing to open an HTTPS request where legacy cert data is
    present, that data will be converted into a Certificate. If that
    certificate's associated hostname (either the Common Name or any
    Subject Alternative Names) is a match for the address, then it will be
    saved as a new certificate and the legacy data removed. If there are any
    problems, the legacy data will be used with a legacy SSL context
    disabling hostname checks, logging warnings until the admin deals with
    the problem.

    For testing, some changes needed to be made to testing infrastructure.
    A utility SSL context for the CertificateManager tests has been made
    commonly available as CaptureSSLContext, and a new test cert has been
    added. Along with this, CertificateManager no longer computes the data
    directory until it needs it, allowing the test harness to switch that to
    a temporary location for the test run.

    Hosting services have not yet been updated to raise the modern
    CertificateVerificationError. The legacy UnverifiedCertificateError
    exception is still supported.

    Unit tests passed.

    Tested this with a couple of self-hosted services against self-signed
    SSL certificates. Verified that I got the right error when I tried to
    communicate with a server, and got the trust banner.

    Tested that trusting the host added the certificate.

    Tested migrating legacy SSL data from a hosting account, and verifying
    it added the new certificate.

    Summary ID
    Add certificate support for hosting services.
    This introduces modern certificate support for all hosting services. The work required for this is a bit different than just using a cert-populated SSL context for `urlopen()`, as hosting services historically have supported storing approved SSL certificate data as part of the `HostingServiceAccount`. Those were conducted with hostname checks turned off. That added a bit of complexity and required a migration path. Now, when preparing to open an HTTPS request where legacy cert data is present, that data will be converted into a `Certificate`. If that certificate's associated hostname (either the Common Name or any Subject Alternative Names) is a match for the address, then it will be saved as a new certificate and the legacy data removed. If there are any problems, the legacy data will be used with a legacy SSL context disabling hostname checks, logging warnings until the admin deals with the problem. For testing, some changes needed to be made to testing infrastructure. A utility SSL context for the `CertificateManager` tests has been made commonly available as `CaptureSSLContext`, and a new test cert has been added. Along with this, `CertificateManager` no longer computes the data directory until it needs it, allowing the test harness to switch that to a temporary location for the test run. Hosting services have not yet been updated to raise the modern `CertificateVerificationError`. The legacy `UnverifiedCertificateError` exception is still supported.
    52583d104f8826af06a7d590124c90667d79df18
    Description From Last Updated

    This doesn't appear to be used for logging context in the implementation. Did you want to include it in log …

    david david

    We're no longer setting self.data['ssl_cert'] but in the case that we get a LegacyUnverifiedCertificateError, the re-authorization in HostingServiceHTTPRequest.open checks for …

    david david

    This will end up creating a cert for http/port 80, which seems... odd. We should probably at least log something.

    david david

    In the case that we get an exception from this, the hostname can be None, leaving this method doing nothing …

    david david

    Should we make a mixin that includes this for setup/teardown?

    david david

    It also might be nice to set this via addCleanup at the beginning of the setUp method instead of putting …

    david david

    Copy/pasteo: Docstring says legacy but the implementation uses the new exception.

    david david

    local variable 'e' is assigned to but never used Column: 13 Error code: F841

    reviewbot reviewbot

    If trust_host == True and cert is None, this falls through silently, leaving reauth as False, and we'll proceed as …

    david david
    david
    1. 
        
    2. reviewboard/hostingsvcs/base/http.py (Diff revision 1)
       
       
       
       
      Show all issues

      This doesn't appear to be used for logging context in the implementation. Did you want to include it in log messages, or should it just be removed?

      1. Yeah, it was originally used but not anymore. I'll remove it.

    3. reviewboard/hostingsvcs/models.py (Diff revision 1)
       
       
      Show all issues

      We're no longer setting self.data['ssl_cert'] but in the case that we get a LegacyUnverifiedCertificateError, the re-authorization in HostingServiceHTTPRequest.open checks for its presence.

      1. Right, it's meant to be loud and persistent and noisy, and to try again until fixed. This represents an insecure setup requiring work. I'll add a comment to that effect.

    4. reviewboard/hostingsvcs/models.py (Diff revision 1)
       
       
       
      Show all issues

      This will end up creating a cert for http/port 80, which seems... odd. We should probably at least log something.

    5. reviewboard/hostingsvcs/models.py (Diff revision 1)
       
       
       
       
       
      Show all issues

      In the case that we get an exception from this, the hostname can be None, leaving this method doing nothing entirely silently.

      We should probably log something if we get an exception, and maybe also log if the hostname is falsy.

    6. Show all issues

      Should we make a mixin that includes this for setup/teardown?

      1. Yeah but in a separate change. I want to revisit some of this, because a few things are scattered.

    7. Show all issues

      It also might be nice to set this via addCleanup at the beginning of the setUp method instead of putting it in tearDown, in case something in test setup fails.

      1. This only ends up mattering if the test actually runs, because it's what populates state.

        I have a thought on how I want to approach this in a more general way but I want to think about that separately from this change at this point.

    8. Show all issues

      Copy/pasteo: Docstring says legacy but the implementation uses the new exception.

    9. 
        
    chipx86
    Review request changed
    Change Summary:
    • Checked for deprecation warnings in unit tests.
    • Updated for RB8.
    • Removed the unused request_url attribute.
    • Added a comment about the noisy logging around unsafe certs.
    • Certs can no longer be accepted for http:// URLs, and will be logged.
    • Exceptions when accepting a legacy cert or when failing to get a hostname are now logged.
    • Fixed a bad test docstring.
    Commits:
    Summary ID
    Add certificate support for hosting services.
    This introduces modern certificate support for all hosting services. The work required for this is a bit different than just using a cert-populated SSL context for `urlopen()`, as hosting services historically have supported storing approved SSL certificate data as part of the `HostingServiceAccount`. Those were conducted with hostname checks turned off. That added a bit of complexity and required a migration path. Now, when preparing to open an HTTPS request where legacy cert data is present, that data will be converted into a `Certificate`. If that certificate's associated hostname (either the Common Name or any Subject Alternative Names) is a match for the address, then it will be saved as a new certificate and the legacy data removed. If there are any problems, the legacy data will be used with a legacy SSL context disabling hostname checks, logging warnings until the admin deals with the problem. For testing, some changes needed to be made to testing infrastructure. A utility SSL context for the `CertificateManager` tests has been made commonly available as `CaptureSSLContext`, and a new test cert has been added. Along with this, `CertificateManager` no longer computes the data directory until it needs it, allowing the test harness to switch that to a temporary location for the test run. Hosting services have not yet been updated to raise the modern `CertificateVerificationError`. The legacy `UnverifiedCertificateError` exception is still supported.
    d418982060ff27bf044f932bddcd018de2f83dd6
    Add certificate support for hosting services.
    This introduces modern certificate support for all hosting services. The work required for this is a bit different than just using a cert-populated SSL context for `urlopen()`, as hosting services historically have supported storing approved SSL certificate data as part of the `HostingServiceAccount`. Those were conducted with hostname checks turned off. That added a bit of complexity and required a migration path. Now, when preparing to open an HTTPS request where legacy cert data is present, that data will be converted into a `Certificate`. If that certificate's associated hostname (either the Common Name or any Subject Alternative Names) is a match for the address, then it will be saved as a new certificate and the legacy data removed. If there are any problems, the legacy data will be used with a legacy SSL context disabling hostname checks, logging warnings until the admin deals with the problem. For testing, some changes needed to be made to testing infrastructure. A utility SSL context for the `CertificateManager` tests has been made commonly available as `CaptureSSLContext`, and a new test cert has been added. Along with this, `CertificateManager` no longer computes the data directory until it needs it, allowing the test harness to switch that to a temporary location for the test run. Hosting services have not yet been updated to raise the modern `CertificateVerificationError`. The legacy `UnverifiedCertificateError` exception is still supported.
    2df6c47315e47079cacff42291b0e1d2e03acd6d

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    chipx86
    david
    1. 
        
    2. reviewboard/hostingsvcs/base/forms.py (Diff revision 3)
       
       
      Show all issues

      If trust_host == True and cert is None, this falls through silently, leaving reauth as False, and we'll proceed as if authorization succeeded.

      We should probably log and reraise the error.

    3. 
        
    chipx86
    Review request changed
    Change Summary:
    • Added logging for the implementation case where a cert instance is missing.
    Commits:
    Summary ID
    Add certificate support for hosting services.
    This introduces modern certificate support for all hosting services. The work required for this is a bit different than just using a cert-populated SSL context for `urlopen()`, as hosting services historically have supported storing approved SSL certificate data as part of the `HostingServiceAccount`. Those were conducted with hostname checks turned off. That added a bit of complexity and required a migration path. Now, when preparing to open an HTTPS request where legacy cert data is present, that data will be converted into a `Certificate`. If that certificate's associated hostname (either the Common Name or any Subject Alternative Names) is a match for the address, then it will be saved as a new certificate and the legacy data removed. If there are any problems, the legacy data will be used with a legacy SSL context disabling hostname checks, logging warnings until the admin deals with the problem. For testing, some changes needed to be made to testing infrastructure. A utility SSL context for the `CertificateManager` tests has been made commonly available as `CaptureSSLContext`, and a new test cert has been added. Along with this, `CertificateManager` no longer computes the data directory until it needs it, allowing the test harness to switch that to a temporary location for the test run. Hosting services have not yet been updated to raise the modern `CertificateVerificationError`. The legacy `UnverifiedCertificateError` exception is still supported.
    833aad80e66112474981e9e720790c110a4dcdce
    Add certificate support for hosting services.
    This introduces modern certificate support for all hosting services. The work required for this is a bit different than just using a cert-populated SSL context for `urlopen()`, as hosting services historically have supported storing approved SSL certificate data as part of the `HostingServiceAccount`. Those were conducted with hostname checks turned off. That added a bit of complexity and required a migration path. Now, when preparing to open an HTTPS request where legacy cert data is present, that data will be converted into a `Certificate`. If that certificate's associated hostname (either the Common Name or any Subject Alternative Names) is a match for the address, then it will be saved as a new certificate and the legacy data removed. If there are any problems, the legacy data will be used with a legacy SSL context disabling hostname checks, logging warnings until the admin deals with the problem. For testing, some changes needed to be made to testing infrastructure. A utility SSL context for the `CertificateManager` tests has been made commonly available as `CaptureSSLContext`, and a new test cert has been added. Along with this, `CertificateManager` no longer computes the data directory until it needs it, allowing the test harness to switch that to a temporary location for the test run. Hosting services have not yet been updated to raise the modern `CertificateVerificationError`. The legacy `UnverifiedCertificateError` exception is still supported.
    52583d104f8826af06a7d590124c90667d79df18

    Checks run (2 succeeded)

    flake8 passed.
    JSHint passed.
    maubin
    1. Ship It!
    2.