Support connecting to hosting services with self-signed certificates.
Review Request #9766 — Created March 12, 2018 and submitted
Most hosting services are third-party systems that will be served with
valid, secure SSL certificates. A few (such as rb-gateway, gerrit, or
GitLab) are run locally, and therefore may be deployed using self-signed
certificates. Until a couple years ago, this wasn't a problem, because
Python's urllib2 implementation didn't actually check SSL certificates
for validity. As of 2.7.9, it does.We had some infrastructure in place for accepting invalid or self-signed
certificates, but it was only implemented for SCMTools, and even then
only for SVN and Perforce. Accepting certificates for services that were
connected to via urllib2, and especially services that go through a
HostingService, was not implemented.This change does that. We now check for SSL-related errors when
attempting to authorize the account. In that case, we'll fetch and
decode the certificate, and show the "I trust this host" prompt to the
user. If the user accepts, we'll store the certificate in the
HostingServiceAccount
'sdata
field. Future attempts to use that
account will then add that certificate to the validation change (and
disable hostname checking, since self-signed certificates often are not
pinned to the correct hostname).
Set up rb-gateway using a self-signed certificate (along with a pending
change to enable SSL in rb-gateway) and attempted to connect it. Saw
the SSL certificate prompt, and selected "I trust this host". The
repository entry was saved, and theHostingServiceAccount.data
field
contained the SSL certificate. Did some operations against the new
repository and saw that they completed successfully.
Description | From | Last Updated |
---|---|---|
F401 'reviewboard.hostingsvcs.service.HostingServiceClient' imported but unused |
reviewbot | |
F841 local variable 'fingerprint' is assigned to but never used |
reviewbot | |
F401 'urllib2.HTTPError' imported but unused |
reviewbot | |
, optional |
chipx86 | |
Can we make these part of the function signature? Prevents crashes in exception handling if the keys are somehow missing. |
chipx86 | |
We should probably localize this. |
chipx86 | |
Can we introduce a named logger for this file, to provide some context? |
chipx86 | |
This can be a bit nicer as: if 'CERTIFICATE_VERIFY_FAILED' not in six.text_type(e): raise # Rest of the stuff here, sans … |
chipx86 | |
Are these in a specific format that we can document? |
chipx86 | |
Can you specify the format the fingerprint will be in? |
chipx86 | |
So I found out about this. This is an authentication realm, and is designed to provide just a bit of … |
chipx86 | |
This doesn't exist in Python pre-2.7.9. Can you add a comment about the version requirement and that we shouldn't have … |
chipx86 | |
I believe we can end up in a situation where we hit this error on older Python 2.7.x releases (predating … |
chipx86 |
- Commit:
-
5f3880e501f21d1f7d9073bd834d5b71a629850a766fcc50a0296d8ba6e02a0e09937a592850701f
Checks run (2 succeeded)
-
This is excellent. Thanks for taking this on!
-
Can we make these part of the function signature? Prevents crashes in exception handling if the keys are somehow missing.
-
-
-
This can be a bit nicer as:
if 'CERTIFICATE_VERIFY_FAILED' not in six.text_type(e): raise # Rest of the stuff here, sans extra indentation.
-
-
-
So I found out about this. This is an authentication realm, and is designed to provide just a bit of additional context as to what's being logged into, mainly for error messages. It's not really part of SSL itself, more a SVN thing, I believe.
So perhaps what we want is to replace this with a dictionary of extra metadata to go along with the certificate, and have SVN populate that with "realm" and pull it out of there as needed.
- Commit:
-
766fcc50a0296d8ba6e02a0e09937a592850701f6b39cf9da347f5c86e9a69bc508c927499789e0b
Checks run (2 succeeded)
-
-
This doesn't exist in Python pre-2.7.9. Can you add a comment about the version requirement and that we shouldn't have been able to make it here on older versions due to the lack of
ssl_cert
indata
? -
I believe we can end up in a situation where we hit this error on older Python 2.7.x releases (predating the better SSL support in 2.7.9) for bad SSL certificates, and then we'd end up calling into
ssl.*
functions that don't exist in that version. Let's wire things off so that we don't get any further if we're running 2.7.8 or lower:if ('CERTIFICATE_VERIFY_FAILED' not in six.text_type(e) or not hasattr(ssl, 'create_default_context')): raise