Skip to content
This repository was archived by the owner on Jan 13, 2021. It is now read-only.

Add support of AppEngine SSL library #193

Closed
wants to merge 8 commits into from

Conversation

jmuk
Copy link

@jmuk jmuk commented Jan 25, 2016

This is a patch to provide the SSL comptibility module working within AppEngine. This change does not enable hyper working on AppEngine yet, but I think this would help approaching to it.

OP_NO_COMPRESSION = 0


class SSLContext:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a minor thing, but can we explicitly inherit from object here? It's unnecessary with Python 3, but old-style classes are a nasty surprise when working in Python 2 code and so it'd be good if we could save ourselves the hassle.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@Lukasa
Copy link
Member

Lukasa commented Jan 25, 2016

Thanks for this @jmuk!

I've left a bit of inline feedback, but I'm interested in getting an idea of how much time you have to spend here. It'd be really great if we could add some tests to validate that all of this logic works correctly, but as you've pointed out, hyper doesn't directly work with GAE yet even with this patch in place. Are you expecting multiple patches to come down the line shortly to add that function? If you are, I'd be interested in having these PRs land in a parallel branch to the mainline development so that we can get them all in place and then add tests in one fell swoop before merging to mainline.

@jmuk
Copy link
Author

jmuk commented Jan 25, 2016

Thank you for the quick reply.

I'll provide the fixes on your comments, but for the questions; I'm good to be within a separate branch. I actually have another CL for the usage of socket.recv_into (which is not implemented yet), but that is all I've noticed. after that hyper will work on GAE -- I mean, at least it can behave as a http2 client in the way I tried, some may be missing though.

# AppEngine SSLSocket does not have selected_npn_protocol nor
# selected_alpn_protocol, so just avoid this assertion.
assert is_appengine or (
proto in H2_NPN_PROTOCOLS or proto == H2C_PROTOCOL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think I wasn't clear enough with my previous feedback. When I was asking about H2C_PROTOCOL I wanted to know why you chose that over h2. h2c is meant to be reserved for HTTP/2 via opportunistic encryption, which seemed an odd choice. I'd be happy to use h2.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, pushed a new patch -- now it uses 'h2'

@jmuk
Copy link
Author

jmuk commented Jan 26, 2016

Added test cases, this will make travis green.

ssl_sock = context.wrap_socket(sock)
assert ssl_sock.selected_npn_protocol() == 'h2'
ssl_sock.close()
self.tear_down()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably these tests should only run if we're actually running on GAE or in a GAE-like system? Otherwise they don't really prove all that much.

I think we need to mark these test classes with pytest.mark.skipif() and use similar logic to what urllib3 uses for its GAE tests, and then add that to the matrix of tests we run on Travis. That might be a little tricky: do you want me to handle doing that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also a timing issue here: the socket_handler really needs to wait until the connection is made and the assertions have been made before any of the tests run. Otherwise, you get problems like the one you can see in the travis run.

The easiest way to do this is to use threading events to synchronise the activity.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GAE doesn't offer a different ssl library actually, it's the same ssl as bundled in future version of Python, but the values in the ssl module is slightly limited. SSLContext doesn't exist, for example.

That means that this ssl_compat_appengine should work with the normal ssl module outside of AppEngine (if it's newer than 2.7.9), and the test case would be still useful to verify the behavior of the module itself.

For the second comment, thank you for catching that. I put sock.do_handshake() on socket_handler so that it verifies to establish the connection, so I think that's good enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, if this should work outside GAE then it's probably enough to just add an extra test environment to validate that it also works on GAE. If we're going to support GAE then we should support it properly! =D

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'm afraid it's not possible to verify if it works on GAE here on travisCI. Actually the local emulator (dev_appserver) in AppEngine SDK simply uses the local runtime with local ssl library, so that doesn't mean the actual GAE environment.

Google could put a test case in its internal end-to-end test cases if hyper is listed in the bundled third party libraries (https://cloud.google.com/appengine/docs/python/tools/libraries27?hl=en), but that's anyways out of the scope right now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, ok, fair enough. In that case, let me do a final code review now. =)

@Lukasa
Copy link
Member

Lukasa commented Jan 26, 2016

Your Python 3.2 test failures are also hitting an issue that I just resolved in #194. You may want to rebase on top of development in order to obtain the fix.

jmuk added 6 commits January 26, 2016 12:02
AppEngine is a special environment, it's in some older version
of Python but it has ssl library, and the library availability is
slightly different from standard python runtimes. This change
provides a compatibility layer working with AppEngine ssl library.
- SSLContext now inherits from object
- stop faking selected_npn_protocol, but fix on the assertion
  on the protocol so that it won't raise failures even when
  it does not exist.
- do_handshake_on_connect to False, because appengine test server
  disconnect immediately on connect.
@jmuk
Copy link
Author

jmuk commented Jan 28, 2016

It seems I've forgotten to reply, but yeah, I've rebased to the top of development, and now it succeeds.

Is there anything I should do?

@@ -31,6 +38,9 @@ def ignore_missing():
if is_py2:
if is_py2_7_9_or_later:
import ssl
elif is_appengine:
from . import ssl_compat_appengine
ssl = ssl_compat_appengine
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this order of fallbacks correct? It seems like if GAE identifies itself as Python 2.7.9 or later then we won't use the AppEngine compatibility module. Having not used GAE myself I'm not sure if this order is right...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, use ssl_compat_appengine when appengine.

When an AppEngine runtime got updated to Python 2.7.9 or later, I was personally thinking that it will use the bundled ssl and this compatibility module becomes unnecessary.
Indeed, however, nothing is sure for now, and anyways this would work with bundled ssl as I commented on another place, using it for GAE environment would be at least harmless even in that.

@Lukasa
Copy link
Member

Lukasa commented Jan 28, 2016

M'kay, I have one smaller question about the order of fallbacks.

@jmuk
Copy link
Author

jmuk commented Jan 29, 2016

Sorry, I've come to realize that the lack of npn/alpn protocol could be significant, and adding them can't be done in hyper -- ssl library (in appengine runtime) needs to be updated. That means, unfortunately this current patch is insufficient, and some details in this PR should be changed when ssl library is updated.

Let me close this PR for the time being. Thank you for your reviews.

@jmuk jmuk closed this Jan 29, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants