Commit dbb066d2 authored by Jim Fulton's avatar Jim Fulton

Added the ability to pass credentials when creating client storages.

This is experimental in that passing credentials will cause
connections to an ordinary ZEO server to fail, but it facilitates
experimentation with custom ZEO servers. Doing this with custom ZEO
clients would have been awkward due to the many levels of
composition involved.

In the future, we expect to support server security plugins that
consume credentials for authentication (typically over SSL).

Note that credentials are opaque to ZEO. They can be any object with
a true value.  The client mearly passes them to the server, which
will someday pass them to a plugin.
parent 02943acd
Changelog Changelog
========= =========
- Added the ability to pass credentials when creating client storages.
This is experimental in that passing credentials will cause
connections to an ordinary ZEO server to fail, but it facilitates
experimentation with custom ZEO servers. Doing this with custom ZEO
clients would have been awkward due to the many levels of
composition involved.
In the future, we expect to support server security plugins that
consume credentials for authentication (typically over SSL).
Note that credentials are opaque to ZEO. They can be any object with
a true value. The client mearly passes them to the server, which
will someday pass them to a plugin.
5.0.0a1 (2016-07-21) 5.0.0a1 (2016-07-21)
-------------------- --------------------
......
...@@ -99,6 +99,7 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage): ...@@ -99,6 +99,7 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
wait=True, wait=True,
drop_cache_rather_verify=True, drop_cache_rather_verify=True,
username=None, password=None, realm=None, username=None, password=None, realm=None,
credentials=None,
# For tests: # For tests:
_client_factory=ZEO.asyncio.client.ClientThread, _client_factory=ZEO.asyncio.client.ClientThread,
): ):
...@@ -261,6 +262,7 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage): ...@@ -261,6 +262,7 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
ZEO.asyncio.client.Fallback if read_only_fallback else read_only, ZEO.asyncio.client.Fallback if read_only_fallback else read_only,
wait_timeout or 30, wait_timeout or 30,
ssl = ssl, ssl_server_hostname=ssl_server_hostname, ssl = ssl, ssl_server_hostname=ssl_server_hostname,
credentials=credentials,
) )
self._call = self._server.call self._call = self._server.call
self._async = self._server.async self._async = self._server.async
......
...@@ -73,7 +73,8 @@ class Protocol(base.Protocol): ...@@ -73,7 +73,8 @@ class Protocol(base.Protocol):
def __init__(self, loop, def __init__(self, loop,
addr, client, storage_key, read_only, connect_poll=1, addr, client, storage_key, read_only, connect_poll=1,
heartbeat_interval=60, ssl=None, ssl_server_hostname=None): heartbeat_interval=60, ssl=None, ssl_server_hostname=None,
credentials=None):
"""Create a client interface """Create a client interface
addr is either a host,port tuple or a string file name. addr is either a host,port tuple or a string file name.
...@@ -93,6 +94,7 @@ class Protocol(base.Protocol): ...@@ -93,6 +94,7 @@ class Protocol(base.Protocol):
self.futures = {} # { message_id -> future } self.futures = {} # { message_id -> future }
self.ssl = ssl self.ssl = ssl
self.ssl_server_hostname = ssl_server_hostname self.ssl_server_hostname = ssl_server_hostname
self.credentials = credentials
self.connect() self.connect()
...@@ -178,17 +180,19 @@ class Protocol(base.Protocol): ...@@ -178,17 +180,19 @@ class Protocol(base.Protocol):
self._write(self.protocol_version) self._write(self.protocol_version)
credentials = (self.credentials,) if self.credentials else ()
try: try:
try: try:
server_tid = yield self.fut( server_tid = yield self.fut(
'register', self.storage_key, 'register', self.storage_key,
self.read_only if self.read_only is not Fallback else False, self.read_only if self.read_only is not Fallback else False,
) *credentials)
except ZODB.POSException.ReadOnlyError: except ZODB.POSException.ReadOnlyError:
if self.read_only is Fallback: if self.read_only is Fallback:
self.read_only = True self.read_only = True
server_tid = yield self.fut( server_tid = yield self.fut(
'register', self.storage_key, True) 'register', self.storage_key, True, *credentials)
else: else:
raise raise
else: else:
...@@ -284,7 +288,7 @@ class Client(object): ...@@ -284,7 +288,7 @@ class Client(object):
def __init__(self, loop, def __init__(self, loop,
addrs, client, cache, storage_key, read_only, connect_poll, addrs, client, cache, storage_key, read_only, connect_poll,
register_failed_poll=9, register_failed_poll=9,
ssl=None, ssl_server_hostname=None): ssl=None, ssl_server_hostname=None, credentials=None):
"""Create a client interface """Create a client interface
addr is either a host,port tuple or a string file name. addr is either a host,port tuple or a string file name.
...@@ -302,6 +306,7 @@ class Client(object): ...@@ -302,6 +306,7 @@ class Client(object):
self.client = client self.client = client
self.ssl = ssl self.ssl = ssl
self.ssl_server_hostname = ssl_server_hostname self.ssl_server_hostname = ssl_server_hostname
self.credentials = credentials
for name in Protocol.client_delegated: for name in Protocol.client_delegated:
setattr(self, name, getattr(client, name)) setattr(self, name, getattr(client, name))
self.cache = cache self.cache = cache
...@@ -367,6 +372,7 @@ class Client(object): ...@@ -367,6 +372,7 @@ class Client(object):
self.storage_key, self.read_only, self.connect_poll, self.storage_key, self.read_only, self.connect_poll,
ssl=self.ssl, ssl=self.ssl,
ssl_server_hostname=self.ssl_server_hostname, ssl_server_hostname=self.ssl_server_hostname,
credentials=self.credentials,
) )
for addr in self.addrs for addr in self.addrs
] ]
...@@ -730,10 +736,12 @@ class ClientThread(ClientRunner): ...@@ -730,10 +736,12 @@ class ClientThread(ClientRunner):
def __init__(self, addrs, client, cache, def __init__(self, addrs, client, cache,
storage_key='1', read_only=False, timeout=30, storage_key='1', read_only=False, timeout=30,
disconnect_poll=1, ssl=None, ssl_server_hostname=None): disconnect_poll=1, ssl=None, ssl_server_hostname=None,
credentials=None):
self.set_options(addrs, client, cache, storage_key, read_only, self.set_options(addrs, client, cache, storage_key, read_only,
timeout, disconnect_poll, timeout, disconnect_poll,
ssl=ssl, ssl_server_hostname=ssl_server_hostname) ssl=ssl, ssl_server_hostname=ssl_server_hostname,
credentials=credentials)
self.thread = threading.Thread( self.thread = threading.Thread(
target=self.run, target=self.run,
name="%s zeo client networking thread" % client.__name__, name="%s zeo client networking thread" % client.__name__,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment