From 2d8bcb4c0f3465619906ea41c688fb8f46174623 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 20 Jul 2022 16:21:25 -0400 Subject: [PATCH] Incorporate auto discovery for remote discovery Avail ourselves of secure vouching to handle new and replaced. --- confluent_server/confluent/config/attributes.py | 2 +- confluent_server/confluent/discovery/core.py | 10 +++++++++- confluent_server/confluent/util.py | 12 ++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py index 5444e0d7..c25045c6 100644 --- a/confluent_server/confluent/config/attributes.py +++ b/confluent_server/confluent/config/attributes.py @@ -256,7 +256,7 @@ node = { 'so long as the node has no existing public key. ' '"open" allows discovery even if a known public key ' 'is already stored', - 'validlist': ('manual', 'permissive', 'pxe', 'open'), + 'validlist': ('manual', 'permissive', 'pxe', 'open', 'verified'), }, 'info.note': { 'description': 'A field used for administrators to make arbitrary ' diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index 7e8b90ed..05ab0a21 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -1153,7 +1153,15 @@ def discover_node(cfg, handler, info, nodename, manual): 'pubkeys.tls_hardwaremanager attribute is cleared ' 'first'.format(nodename)}) return False # With a permissive policy, do not discover new - elif policies & set(('open', 'permissive')) or manual: + elif policies & set(('open', 'permissive', 'verified')) or manual: + if 'verified' in policies: + if not handler.https_supported or not util.cert_matches(info['fingerprint'], handler.https_cert): + log.log({'info': 'Detected replacement of {0} without verified ' + 'fingerprint and discovery policy is setto verified, not ' + 'doing discovery unless discovery.policy=open or ' + 'pubkeys.tls_hardwaremanager attribute is cleared ' + 'first'.format(nodename)}) + return False info['nodename'] = nodename if info['handler'] == pxeh: return do_pxe_discovery(cfg, handler, info, manual, nodename, policies) diff --git a/confluent_server/confluent/util.py b/confluent_server/confluent/util.py index 52726302..35b1e08e 100644 --- a/confluent_server/confluent/util.py +++ b/confluent_server/confluent/util.py @@ -146,12 +146,24 @@ def get_fingerprint(certificate, algo='sha512'): return 'sha256$' + hashlib.sha256(certificate).hexdigest() elif algo == 'sha512': return 'sha512$' + hashlib.sha512(certificate).hexdigest() + elif algo == 'sha384': + return 'sha384$' + hashlib.sha384(certificate).hexdigest() raise Exception('Unsupported fingerprint algorithm ' + algo) +hashlens = { + 48: hashlib.sha384, + 64: hashlib.sha512, + 32: hashlib.sha256 +} + def cert_matches(fingerprint, certificate): if not fingerprint or not certificate: return False + if '$' not in fingerprint: + fingerprint = base64.b64decode(certificate) + algo = hashlens[len(fingerprint)] + return algo(certificate).digest() == fingerprint algo, _, fp = fingerprint.partition('$') newfp = None if algo in ('sha512', 'sha256'):