-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Integrate TLS-in-TLS support into urllib3 #1923
Integrate TLS-in-TLS support into urllib3 #1923
Conversation
For connections that will attempt to use an HTTPS proxy with an HTTPS destination, we'll use the TLS in TLS support provided by SSL Transport. HTTPS proxy and HTTP destinations will continue using a single TLS session as expected. We'll still support the use of forwarding for HTTPS destinations with HTTPS proxies as long as the "use_forwarding_for_https" parameter is provided. Signed-off-by: Jorge Lopez Silva <jalopezsilva@gmail.com>
542b8ff
to
4ff1d93
Compare
All right rebased after the closure of #1806, this should be good to review! I'll add subsequent commits when addressing feedback to make it easier. |
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.
Great start to this, very exciting :) Left some comments and questions for you.
cc @nateprewitt for when Requests will inevitably be asked about HTTPS proxy support
src/urllib3/util/proxy.py
Outdated
proxy_cert, proxy_key, proxy_pass = client_certificate_and_key_from_env() | ||
|
||
if proxy_cert: | ||
ssl_context.load_cert_chain(proxy_cert, keyfile=proxy_key, password=proxy_pass) |
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.
If proxy_pass
isn't given we shouldn't call with the password
parameter. The parameter isn't supported on some Python 2.7 if I recall
src/urllib3/util/proxy.py
Outdated
Attempts to retrieve a client certificate and key from the environment | ||
variables to use with the proxy. | ||
""" | ||
proxy_cert = os.environ.get("PROXY_SSLCERT") |
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.
So I'm kinda in -1 territory when it comes to environment variables. Ideally our users would make these sorts of things configurable with their own interfaces. We don't support setting connection TLS config w/ environment variables either.
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 agree with you in principle. Ideally all libraries should provide interfaces that allow clients to pass through a proxy ssl context and any necessary parameters to urllib3. I already have prepared upstream patches to do this for botocore and requests. I'll send those out once we release the changes in urllib3.
That said though, there's a ton of libraries out there that would need clients to prepare PRs or changes to allow these parameters to go through. It seems easier to support those through environment variables for the time being.
Are you concerned about these being accidentally set? Could prefixing them by URLLIB3_*
address that concern?
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.
Knowing when to use environment variables versus parameters in the program versus OS defaults is a big can of worms as we know from Requests, so I want to mark it out of scope for this PR and release. I can definitely see the value, I don't want to release it as a part of 1.26 though.
I appreciate that you have PRs for boto and requests though, that will be very useful! :)
Another thing I thought of while working through the docs overhaul: I think that |
- Make the toggle for absolute URI forwarding public and adjust documentation. - Adjust documentation in util/proxy.py for connection_requires_http_tunnel. - Only set the proxy_pass if the pass was provided. - Adjust unsupported ssl.SSLContext check. - Remove 'server_hostname' parameter on platforms without SNI support. - Better handling and passing of destination scheme between connectionpool and connection.
PR has been updated with two additional commits. Commit #2 addresses the feedback received above. All of the items were addressed, let me know if I missed anything. Commit #3 moved SSLTransport from contrib to util as requested by @sethmlarson. It seems there are some merge failures, I'll rebase once you've had a chance to review the two additional commits. |
- Mistake in previous commit.
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.
Some more comments! :)
src/urllib3/util/proxy.py
Outdated
Attempts to retrieve a client certificate and key from the environment | ||
variables to use with the proxy. | ||
""" | ||
proxy_cert = os.environ.get("PROXY_SSLCERT") |
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.
Knowing when to use environment variables versus parameters in the program versus OS defaults is a big can of worms as we know from Requests, so I want to mark it out of scope for this PR and release. I can definitely see the value, I don't want to release it as a part of 1.26 though.
I appreciate that you have PRs for boto and requests though, that will be very useful! :)
Codecov Report
@@ Coverage Diff @@
## master #1923 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 24 25 +1
Lines 2187 2243 +56
=========================================
+ Hits 2187 2243 +56
Continue to review full report at Codecov.
|
- Improve documentation syntax. - Use Python 2 instead of py2. - Remove support for configuring through environment variables. - Nit and suggestions on util.ssl_.py - Improvements on validation and error messages for not supported SSLContext.
Great work on improving the CI! It's working much more reliably now and it's also faster? (or is it just my impression?) In any case, I've updated the PR with two additional commits: One performs a merge with current Let me know if we need more changes. I'll follow up on another PR for adding the missing tests on |
@jalopezsilva That's all thanks to @pquentin and @hodbn! There's been so much work put into our CI and it's really paying off 👏 |
- Move to staticmethod instead of classmethod, also make it private. - Error out if SSLTransport isn't available and we need to do TLS-in-TLS. - Avoid modifying the signature of prepare_proxy.
All right, another commit for the remaining comments. @sethmlarson, happy to add another test case for |
@jalopezsilva On an unrelated note, should we credit your employer for sponsoring your time on this amazing feature? Or was it done on your time? |
@pquentin It's been a little bit of both. FB has been pretty supportive of me upstreaming the changes but I have also put personal time to make sure it goes through! No need to do any special announcements/credits, FB and I will just be happy to know the changes were merged in 😃 |
@sethmlarson Disregard the AppEngine comment, for some reason I thought it implemented the HTTPConnection interface. Doh. |
- We no longer need to pass the upstream destination.
Integration PR after #1806 is closed.
The PR finally integrates the
SSLTransport
class to support TLS-in-TLS tunnels through proxies. This will enable urllib3 to use HTTPS proxies with HTTPS destinations. The previous supported mode, forwarding the absolute URI method, is kept under a flag for HTTPS destinations through HTTPS proxies. I added two new parameters for ProxyManagersproxy_ssl_context
which can be used to pass anSSLContext
to be used with the proxy anduse_forwarding_for_https
which enables the forwarding absolute URI mode.I decided to keep the forwarding mode as it has been incredibly useful within corporate environments when used with trusted proxies. (e.g we can audit no undesired information is sent through requests). This mode is by default disabled and I'm hoping that with enough documentation users won't use it unnecessarily.
I also added three environment variables which can be used to configure the default proxy ssl context.
PROXY_SSLCERT
,PROXY_SSLKEY
,PROXY_SSLPASSWD
. These environment variables will be super useful to configure the proxy ssl context when urllib3 is used within other libraries (e.g botocore, requests, etc)Tests have been added. I have not added documentation yet, but I can do so easily.
Closes #1662