-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
Let the user provide an SSLContext object #2118
Comments
I'm not sure if you mean the fundamental
We're very unlikely to start supporting a keyword argument on only one version of Python. In general I like the idea, but so long as we will support Python 2 (unless a backport of the SSL module can be successfully provided), we will have trouble supporting this. Further, we're ignoring whether or not @kennethreitz would even want to add this keyword argument. I for one would be in favor of adding it (when we can support all Python versions equally), but I don't get to make these decisions ;). That said, I'll have to investigate if urllib3 will support |
Can we step back for a moment? @brandon-rhodes I'm really not clear about what you mean by requests sprouting more and more keywords. We have two: What have I missed? What parameters are you identifying that I don't see? |
Reading your post again @brandon-rhodes, I realise that your concern is not actually that we currently have too many parameters, but that we might end up having too many parameters. In this I agree with you. However, I think requests should continue its proud tradition of solving the 80% use-case in the primary API and allowing the Transport Adapter API to help the remaining 20%. For this reason, I'd never accept adding a Instead, let's look at providing something like the |
By no means did I intend to ignore @kennethreitz’s wishes! Alas. Opening this issue was, I had thought, precisely the means by which Mr. Reitz’s wishes could become known. Would there have been a more appropriate forum for asking my question?
Thank you, @Lukasa! Sorry if I worded the issue awkwardly and it required multiple read-throughs.
So the keyword arguments to The In fact, what I really probably want is an adapter that does not even know that |
No. I just like to couch my positive replies in "But Kenneth might not want this, so don't get your hopes up". It might take him a while to get around to reading or replying though.
That is correct. There are currently a few good examples of this (like the SSLAdapter @Lukasa linked above).
Good news! @Lukasa has a blog post about building adapters for requests and we can both help you with building one of these. Further, I'd be interested in it if only to add it to the
You could do this, but then you would probably doing a lot of It might be more helpful to acquaint yourself further with the adapters that currently exist in requests, to understand how they work. They're not terribly difficult to understand either. |
Okay! I will go take a look at them, and then come back later and comment again on this issue. |
Supplying your own socket factory thing is indeed something urllib3 wants to support. We had some discussions about providing a class which "contains" all the parts you need to make an SSL contexted socket. (urllib3/urllib3#371 (comment) alludes to this) For now, you'd need to set the Here's the meat for our verified SSL stuff: https://github.com/shazow/urllib3/blob/master/urllib3/connection.py#L191 |
Hooray for three person issue conversations! They're always so easy to follow. =) @brandon-rhodes, you've provided lots of great options for us. I'd like to try to enumerate them as I understand them, and then provide feedback on each of them. Please step in if you think I've left anything out or misunderstood something.
|
I'd vote for passing Tornado for example implements a fancy Though, actually all that would be required in urllib3 to make it usable. |
@EnTeQuAk I continue to be in favour of my option 2. =) |
I agree: option 2 is the winner here, and will bring Requests up to the level of capability of the protocol modules in the Standard Library (http.client, smtplib, poplib, imaplib, ftplib, and nntplib) that all also support SSLContext parameters. |
+1, option 2. |
I am going to provide a strawman of option 3, as I believe option 2 is extremely difficult at an engineering level without introducing a new I propose the addition of a new urllib3 utility class, opts = TLSOptions()
opts.allow_compression = True
opts.ciphers = 'TLS_ECDHE_RSA_AES_128_GCM_SHA_256'
opts.versions = ['TLSv1.1', 'TLSv1.2'] This states the options in a manner that is deliberately agnostic to whether Finally, the object could perform meaningful validation of settings: for example, if I had passed the cipher string above with Can I get initial feedback on how this feels to people? |
I'd like to advocate for having |
I second @alex's suggestion. Constructing it once and not having to use those 4 lines each time I need a slight variation is much nicer. Immutability will also be pleasant so the options cannot be changed under anyone's feet. |
I'm happy with immutability. That gets us to this: opts = TLSOptions(
allow_compression=True,
ciphers='TLS_ECDHE_RSA_AES_128_GCM_SHA_256',
versions=['TLSv1.1', 'TLSv1.2']
) |
|
@shazow it's lived almost entirely here so let's just finish it here? |
Are there other options we're considering for this? |
Preface ======= Many times organizations use internal jira servers which are secured by configuring https access with a "self-signed" (or otherwise not publicly verifiable) SSL certificate. Currently, [an exception is raised](http://pastebin.com/DuhTNYDv) when issuing a command to such a server. This Pull-Request's main intent is to allow the user to set options which customize SSL behavior; preferably by passing SSLContext where possible (requests does not yet support it as of now, see issue kennethreitz/requests#2118). Change Details ============== * passed directly to xmlrpclib.ServerProxy constructor * requests only has partial support; `verify` bool option is passed * SOAPpy: no change -> strangely works without raising SSLError
I'm strongly in favor for option 2), the SSLContext object. If we can agree upon a minimalistic API then urllib3 and requests would be able to support more TLS/SSL libraries than just OpenSSL through stdlib ssl module and PyOpenSSL. For example I have a specific use case for NSS as TLS library. Somebody has expressed an interest in SecureTransport (OSX) as TLS lib. I even would go so far and standardize a minimal ABC in a PEP.
I think these attributes and methods are about the bare minimum to define a useful socket, SSL connection and SSLContext. The ABCs deliberately omit all methods to create or configure a socket or a context. It only defines methods to read/write for TCP streaming connections over IPv4 or IPv4 as well as an API to wrap a socket into a SSL socket. Basically SSLContext object is demoted to a factory that turns minimal socket into a SSL-aware socket. For most applications the socket is created and configured elsewhere, usually in a create_connection(). Maybe create_connection() could be a method of SSLContext, too. That would be useful for NSS, because NSPR has its own socket abstraction layer that is not fully compatible with OS sockets.
My idea doesn't contradict Alex's idea for TLSOptions, it just deals with a different level of abstraction. TLSOptions is a useful high level interface for requests. My proposal doesn't care how a SSLContext object for a specific implementation is created. TLSOptions could be used to create ssl.SSLContext or OpenSSL.SSL.Context. But internally requests and urllib3 should really use SSLContext. |
We'll obviously use SSLContexts at the interface to urllib3, because that's what urllib3 will accept. However, in requests land, we may want to use an API that's far clearer. |
Hi, not sure if this thread is the right place, but I just wanted to add my 2 cents from an API user's perspective. Currently, the AFAIU, when we gain a way to supply customized
However, this is obviously suboptimal and involves bad code smells. If you get to implementing SSLContexts support, could you also expose an obvious way in the API (e.g. a callback function) to handle any additional custom validations with access to full certificate data? Basically, a way to get called back with the result of |
@aadamowski You wouldn't need that. Generally speaking, if you can provide an SSLContext you should just use PyOpenSSL and provide Context with a custom verify callback. That would allow you to achieve your goal. |
@Lukasa , is the plan for Despite some similarities, these classes don't have compatible APIs and aren't related. |
Correct, but that's why we would need to have both. Requests can use pyOpenSSL in some circumstances, which means we need to be able to use the pyOpenSSL Context object in some circumstances. This is why this issue has been around so long: it's not as easy as it seems at first glance. ;) |
I came across this issue today after trying to customize the cipher suite for the SSL connection in a Session. For some reason the TLS version and cipher spec were not being automatically negotiated appropriately. I'm still trying to figure out why this is the case. This is an issue that has come up for us multiple times now and we really do need a solution. I do like using the SSLContext object because it is the standard way to customize the ssl connection in Python. In any case, we just need a documented way to specify these parameters. Currently, to force a given TLS version, we implement an HTTPAdapter and use session.mount() with it. But the pool manager only allows us to specify a specific ssl_version to use (packages/urllib3/poolmanager.py). It does not allow us to customize the ciphers or anything else. To provide more context, we have encountered issues using client-side certificates while connecting to Java GlassFish servers that require TLS 1.1/1.2. |
Preface ======= Many times organizations use internal jira servers which are secured by configuring https access with a "self-signed" (or otherwise not publicly verifiable) SSL certificate. Currently, [an exception is raised](http://pastebin.com/DuhTNYDv) when issuing a command to such a server. This Pull-Request's main intent is to allow the user to set options which customize SSL behavior; preferably by passing SSLContext where possible (requests does not yet support it as of now, see issue kennethreitz/requests#2118). Change Details ============== * passed directly to xmlrpclib.ServerProxy constructor * requests only has partial support; `verify` bool option is passed * SOAPpy: no change -> strangely works without raising SSLError
+1 - this would be great to have. It's been almost a year with no movement here. |
No, it hasn't. You can pass SSLContext objects using TransportAdapters as of v2.12.0. |
@Lukasa Are there docs on doing so? I'm not finding anything. |
@dsully Not at this time, though I have written examples a few times. |
@Lukasa Thanks, I'll start playing around with that. FWIW, the reason I need this is adding our internal CA to the trust store in addition to locking down the cipher suite. |
The requests library seems to grow more and more keyword arguments to try to provide all of the flexibility that SSL users need. As of Python 3.2, the Standard Library now offers a different approach: an
SSLContext
that can accept settings for TLS protocol version, CA certificate list, identity certificate, secret key, allowable cipher list, Diffie-Hellman parameters, server-name callback function, whether to verify server hostnames, and so forth. It has awrap_socket()
method that starts up TLS on a socket using precisely the settings it has been configured with.This lets protocol libraries in the Python 3 Standard Library opt out of needing keyword arguments for any of the above settings. They can simply accept a
context=
keyword argument, use the context to wrap their encrypted sockets, and stay out of the business of understanding SSL and all of its different settings.If the requests library under Python 3 started supporting a
context=
parameter like the Standard Library protocols, then users could fine-tune their encryption settings without requests having to become more complicated.A use-case: many users today are concerned about Perfect Forward Security (PFS) and want to only make connections with ciphers that at least make it possible to build connections that cannot be decrypted later if a secret key is captured. But the current requests library, so far as I can see, makes no provision for this. Nor do I want it to: adding a new
ciphers=
keyword would be only the first of a dozen other keywords that SSL users will need added over the coming years. But if requests accepted acontext=
parameter, then I can create anSSLContext
and tell it which protocols I am willing to use and have requests (and urllib3) use that context for building their SSL connections.The text was updated successfully, but these errors were encountered: