New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add support for password protected certificate files #143
Conversation
Codecov Report
@@ Coverage Diff @@
## master #143 +/- ##
==========================================
+ Coverage 75.03% 75.07% +0.03%
==========================================
Files 8 8
Lines 2560 2588 +28
==========================================
+ Hits 1921 1943 +22
- Misses 639 645 +6
Continue to review full report at Codecov.
|
Thanks for work. Ways to improve:
|
I can do the local HTTPS server part maybe this weekend if you like. |
Done. Not sure if we need to hit an external server or a local server. Need to make sure that password is passed through and verified when cert file is loaded. That happens when SSLContext.load_cert_chain() is called before connection is established. I don't think I understand what you mean by no special code for 3.2 needed. |
|
Hey, is there anything needed for this pull request to be merged? Please let me know. |
Test without relying on external network. |
Done. Please let me know if anything else is missing. |
tests/__init__.py
Outdated
return | ||
|
||
|
||
class MockHttpServer(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There already exists code that does same function, right below this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I respectfully disagree with that statement.
The code below doesn't support SSL and has some hacky "with" implementation / object life time management. It's also impossible to get back client cert used by the server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thanks for criticism, I very much agree that code turned out less simple than it should.
So if you disagree here, please wait for me to add https/cert support in existing server stub. There is no good reason to have two testing server implementations.
tests/test_external.py
Outdated
http = httplib2.Http(timeout=2) | ||
http.add_certificate("akeyfile", "acertfile", "bitworking.org", "apassword") | ||
try: | ||
http.request("https://bitworking.org", "GET") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still trying to hit external website.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test without relying on external network.
The test without relying on external network is implemented - test_get_via_https_key_cert_password_with_pem_local_server.
Still trying to hit external website.
Just to clarify, do you expect all tests to use local server? There are quite a few tests which do that in test_external.py file. Or are you referring to newly added tests only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are all transient, were created because local server stub was not implemented or not capable of required features at that time. See file docstring:
"""These tests rely on replies from public internet services
TODO: reimplement with local stubs
"""
@kkoshelev-g please have a look here #147 |
@kkoshelev-g ping |
Sorry for the delay. I don't think so. The proposed code does not allow testing mutual TLS. It is not possible to verify what was the certificate presented by the client from the server side. See cert serial number comparison in the test. The test set up is also more complicated, one needs to pass a lot of args to set proper mutual TLS connection with cert/password. The generation of certificates is fancy but it is not really necessary for the purpose of the testing. |
@kkoshelev-g wow you are brilliant reviewer. Indeed one line was missing to check client certs in most common test server constructor, while present in rarely used one. Line 410 in 3a6d7cd
It's now possible to test client serial as in this test: def test_client_cert_verified():
cert_log = []
def setup_tls(context, server, skip_errors):
context.load_verify_locations(cafile=tests.CA_CERTS)
context.verify_mode = ssl.CERT_REQUIRED
return context.wrap_socket(server, server_side=True)
def handler(request):
cert_log.append(request.client_sock.getpeercert())
return tests.http_response_bytes()
http = httplib2.Http(ca_certs=tests.CA_CERTS)
with tests.server_request(handler, tls=setup_tls) as uri:
uri_parsed = urllib.parse.urlparse(uri)
http.add_certificate(tests.CLIENT_PEM, tests.CLIENT_PEM, uri_parsed.netloc)
http.request(uri)
assert len(cert_log) == 1
# TODO extract serial from tests.CLIENT_PEM
assert cert_log[0]["serialNumber"] == "E2AA6A96D1BF1AEC" |
Thank you for the update. I guess I will have to wait until test framework changes are merged. |
donzo |
Add test_client_cert_password_verified test
I merged latest upstream changes into pull request branch. Please let me know if there is anything missing. |
python2/httplib2/__init__.py
Outdated
@@ -1958,6 +1983,7 @@ def request( | |||
ca_certs=self.ca_certs, | |||
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation, | |||
ssl_version=self.ssl_version, | |||
key_password = certs[0][2], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just this minor spaces around '=', CI linter should've caught this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you.
thank you |
0.15.0 python2: regression in connect() error handling httplib2/httplib2#150 add support for password protected certificate files httplib2/httplib2#143 feature: Http.close() to clean persistent connections and sensitive data httplib2/httplib2#149
0.15.0 python2: regression in connect() error handling httplib2/httplib2#150 add support for password protected certificate files httplib2/httplib2#143 feature: Http.close() to clean persistent connections and sensitive data httplib2/httplib2#149
This should improve the security by protecting private cert key with password when using httplib2 with client certificates to initiate mutual TLS connection. See #142
This adds an optional "password" arg to add_certificate() function.
If "password" is provided then "key" points to password encrypted cert file.
This may break unit-tests due to changes to KeyCerts class. I'm still trying to figure out how to run tests properly. I will provide an update after I resolve those issues.