From 334ce65919405fec3ef1e57e96e90313ea56f65c Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 20 Apr 2022 17:11:01 -0400 Subject: [PATCH] Add facility for forwarding agent Remote discovery will require that the reporting agent provides port forwarding facility for https access, to allow access without route to the managing confluent server. This will allow the info reported to indicate use of this forwarding facility and the base handler adds ability to generically get the certificate. --- confluent_server/confluent/discovery/core.py | 2 + .../confluent/discovery/handlers/generic.py | 40 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index 7ca752a4..98560465 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -429,6 +429,8 @@ def handle_api_request(configmanager, inputdata, operation, pathcomponents): return (msg.KeyValueData({'rescan': 'started'}),) elif operation in ('update', 'create'): + if pathcomponents == ['discovery', 'register']: + return if 'node' not in inputdata: raise exc.InvalidArgumentException('Missing node name in input') mac = _get_mac_from_query(pathcomponents) diff --git a/confluent_server/confluent/discovery/handlers/generic.py b/confluent_server/confluent/discovery/handlers/generic.py index aca0f864..d38058c9 100644 --- a/confluent_server/confluent/discovery/handlers/generic.py +++ b/confluent_server/confluent/discovery/handlers/generic.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import confluent.util as util import errno import eventlet import socket @@ -31,6 +32,15 @@ class NodeHandler(object): self.info = info self.configmanager = configmanager targsa = [None] + self.ipaddr = None + self.relay_url = None + self.relay_server = None + # if this is a remote registered component, prefer to use the agent forwarder + if info.get('forwarder_url', False): + self.relay_url = info['forwarder_url'] + self.relay_server = info['forwarder_server'] + self.relay_token = info['forwarder_token'] + return # first let us prefer LLA if possible, since that's most stable for sa in info['addresses']: if sa[0].startswith('fe80'): @@ -103,11 +113,33 @@ class NodeHandler(object): def https_cert(self): if self._fp: return self._fp - if ':' in self.ipaddr: - ip = '[{0}]'.format(self.ipaddr) + if self.relay_url: + kv = util.TLSCertVerifier(self.configmanager, self.relay_server, + 'pubkeys.tls_hardwaremanager').verify_cert + w = webclient.SecureHTTPConnection(self.relay_server, verifycallback=kv) + relaycreds = self.configmanager.get_node_attributes(self.relay_server, 'secret.*', decrypt=True) + relaycreds = relaycreds.get(self.relay_server, {}) + relayuser = relaycreds.get('secret.hardwaremanagementuser', {}).get('value', None) + relaypass = relaycreds.get('secret.hardwaremanegementpassword', {}).get('value', None) + if not relayuser or not relaypass: + raise Exception('No credentials for {0}'.format(self.relay_server)) + w.set_basic_credentials(relayuser, relaypass) + w.connect() + w.request('GET', self.relay_url) + r = w.getresponse() + rb = r.read() + if r.code != 302: + raise Exception('Unexpected return from forwarder') + newurl = r.getheader('Location') + port = int(newurl.rsplit(':', 1)[-1][:-1]) + ip = self.relay_server else: - ip = self.ipaddr - wc = webclient.SecureHTTPConnection(ip, verifycallback=self._savecert) + port = 443 + if ':' in self.ipaddr: + ip = '[{0}]'.format(self.ipaddr) + else: + ip = self.ipaddr + wc = webclient.SecureHTTPConnection(ip, verifycallback=self._savecert, port=port) try: wc.connect() except IOError as ie: