Merge "Add ZooKeeper TLS support"

This commit is contained in:
Zuul 2020-04-15 01:41:47 +00:00 committed by Gerrit Code Review
commit 775cd32028
8 changed files with 83 additions and 5 deletions

View File

@ -122,6 +122,31 @@ Options
relative to the supplied root path, is also optional and has no
default.
.. attr:: zookeeper-tls
:type: dict
To use TLS connections with Zookeeper, provide this dictionary with
the following keys:
.. attr:: cert
:type: string
:required:
The path to the PEM encoded certificate.
.. attr:: key
:type: string
:required:
The path to the PEM encoded key.
.. attr:: ca
:type: string
:required:
The path to the PEM encoded CA certificate.
.. attr:: labels
:type: list

View File

@ -1372,7 +1372,11 @@ class NodePoolBuilder(object):
# All worker threads share a single ZooKeeper instance/connection.
self.zk = zk.ZooKeeper(enable_cache=False)
self.zk.connect(list(self._config.zookeeper_servers.values()))
self.zk.connect(
list(self._config.zookeeper_servers.values()),
tls_cert=self._config.zookeeper_tls_cert,
tls_key=self._config.zookeeper_tls_key,
tls_ca=self._config.zookeeper_tls_ca)
self.log.debug('Starting listener for build jobs')

View File

@ -61,6 +61,12 @@ class ConfigValidator:
'listen_address': str,
}
zk_tls = dict(
cert=v.Required(str),
key=v.Required(str),
ca=v.Required(str),
)
top_level = {
'webapp': webapp,
'elements-dir': str,
@ -72,6 +78,7 @@ class ConfigValidator:
'port': int,
'chroot': str,
}],
'zookeeper-tls': zk_tls,
'providers': list,
'labels': [label],
'diskimages': [diskimage],

View File

@ -373,7 +373,11 @@ class NodePoolCmd(NodepoolApp):
'list', 'delete',
'request-list', 'info', 'erase'):
self.zk = zk.ZooKeeper(enable_cache=False)
self.zk.connect(list(config.zookeeper_servers.values()))
self.zk.connect(
list(config.zookeeper_servers.values()),
tls_cert=config.zookeeper_tls_cert,
tls_key=config.zookeeper_tls_key,
tls_ca=config.zookeeper_tls_ca)
self.pool.setConfig(config)
self.args.func()

View File

@ -36,6 +36,9 @@ class Config(ConfigValue):
self.providers = {}
self.provider_managers = {}
self.zookeeper_servers = {}
self.zookeeper_tls_cert = None
self.zookeeper_tls_key = None
self.zookeeper_tls_ca = None
self.elementsdir = None
self.imagesdir = None
self.build_log_dir = None
@ -83,6 +86,13 @@ class Config(ConfigValue):
'listen_address': webapp_cfg.get('listen_address', '0.0.0.0')
}
def setZooKeeperTLS(self, zk_tls):
if not zk_tls:
return
self.zookeeper_tls_cert = zk_tls.get('cert')
self.zookeeper_tls_key = zk_tls.get('key')
self.zookeeper_tls_ca = zk_tls.get('ca')
def setZooKeeperServers(self, zk_cfg):
if not zk_cfg:
return
@ -322,6 +332,7 @@ def loadConfig(config_path):
newconfig.setDiskImages(config.get('diskimages'))
newconfig.setLabels(config.get('labels'))
newconfig.setProviders(config.get('providers'))
newconfig.setZooKeeperTLS(config.get('zookeeper-tls'))
# Ensure at least qcow2 is set to be passed to qemu-img.
# Note that this needs to be after setting the providers as they
@ -346,3 +357,4 @@ def loadSecureConfig(config, secure_config_path):
config.setZooKeeperServers(secure.get('zookeeper-servers'))
config.setSecureDiskimageEnv(
secure.get('diskimages', []), secure_config_path)
config.setZooKeeperTLS(secure.get('zookeeper-tls'))

View File

@ -942,7 +942,10 @@ class NodePool(threading.Thread):
if not self.zk and configured:
self.log.debug("Connecting to ZooKeeper servers")
self.zk = zk.ZooKeeper()
self.zk.connect(configured)
self.zk.connect(configured,
tls_cert=config.zookeeper_tls_cert,
tls_key=config.zookeeper_tls_key,
tls_ca=config.zookeeper_tls_ca)
else:
self.log.debug("Detected ZooKeeper server changes")
self.zk.resetHosts(configured)

View File

@ -945,7 +945,8 @@ class ZooKeeper(object):
def resetLostFlag(self):
self._became_lost = False
def connect(self, host_list, read_only=False):
def connect(self, host_list, read_only=False, tls_cert=None,
tls_key=None, tls_ca=None):
'''
Establish a connection with ZooKeeper cluster.
@ -956,11 +957,21 @@ class ZooKeeper(object):
:py:class:`~nodepool.zk.ZooKeeperConnectionConfig` objects
(one per server) defining the ZooKeeper cluster servers.
:param bool read_only: If True, establishes a read-only connection.
:param str tls_key: Path to TLS key
:param str tls_cert: Path to TLS cert
:param str tls_ca: Path to TLS CA cert
'''
if self.client is None:
hosts = buildZooKeeperHosts(host_list)
self.client = KazooClient(hosts=hosts, read_only=read_only)
args = dict(hosts=hosts,
read_only=read_only)
if tls_key:
args['use_ssl'] = True
args['keyfile'] = tls_key
args['certfile'] = tls_cert
args['ca'] = tls_ca
self.client = KazooClient(**args)
self.client.add_listener(self._connection_listener)
# Manually retry initial connection attempt
while True:

View File

@ -0,0 +1,12 @@
---
features:
- |
Support for encrypted connections to ZooKeeper has been added.
Before enabling, ensure that both Zuul and Nodepool software
versions support encrypted connections. See the Zuul release
notes, documentation, and associated helper scripts for more
information.
Both Zuul and Nodepool may need to be restarted together with the
new configuration.