diff --git a/confluent_client/bin/nodediscover b/confluent_client/bin/nodediscover index a14b7358..41ecf8b3 100755 --- a/confluent_client/bin/nodediscover +++ b/confluent_client/bin/nodediscover @@ -57,12 +57,15 @@ def print_disco(options, session, currmac, outhandler, columns): procinfo.update(tmpinfo) if 'Switch' in columns or 'Port' in columns: - for tmpinfo in session.read( - '/networking/macs/by-mac/{0}'.format(currmac)): - if 'ports' in tmpinfo: - # The api sorts so that the most specific available value - # is last - procinfo.update(tmpinfo['ports'][-1]) + if 'switch' in procinfo: + procinfo['port'] = procinfo['switchport'] + else: + for tmpinfo in session.read( + '/networking/macs/by-mac/{0}'.format(currmac)): + if 'ports' in tmpinfo: + # The api sorts so that the most specific available value + # is last + procinfo.update(tmpinfo['ports'][-1]) record = [] for col in columns: rawcol = columnmapping[col] diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index 30df3c09..7e8b90ed 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -217,7 +217,12 @@ def send_discovery_datum(info): if info['handler'] == pxeh: enrich_pxe_info(info) yield msg.KeyValueData({'nodename': info.get('nodename', '')}) - yield msg.KeyValueData({'ipaddrs': [_printable_ip(x) for x in addresses]}) + if not info.get('forwarder_server', None): + yield msg.KeyValueData({'ipaddrs': [_printable_ip(x) for x in addresses]}) + switch = info.get('forwarder_server', None) + if switch: + yield msg.KeyValueData({'switch': switch}) + yield msg.KeyValueData({'switchport': info['port']}) sn = info.get('serialnumber', '') mn = info.get('modelnumber', '') uuid = info.get('uuid', '') @@ -690,6 +695,8 @@ def detected(info): info['otheraddresses'] = set([]) for i4addr in info.get('attributes', {}).get('ipv4-address', []): info['otheraddresses'].add(i4addr) + for i4addr in info.get('attributes', {}).get('ipv4-addresses', []): + info['otheraddresses'].add(i4addr) if handler and handler.https_supported and not handler.https_cert: if handler.cert_fail_reason == 'unreachable': log.log( diff --git a/confluent_server/confluent/discovery/handlers/generic.py b/confluent_server/confluent/discovery/handlers/generic.py index db1d0611..0d41d366 100644 --- a/confluent_server/confluent/discovery/handlers/generic.py +++ b/confluent_server/confluent/discovery/handlers/generic.py @@ -41,7 +41,6 @@ class NodeHandler(object): 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']: @@ -144,7 +143,7 @@ class NodeHandler(object): 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) + relaypass = relaycreds.get('secret.hardwaremanagementpassword', {}).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) diff --git a/confluent_server/confluent/discovery/protocols/ssdp.py b/confluent_server/confluent/discovery/protocols/ssdp.py index 762b643a..85b5d7f1 100644 --- a/confluent_server/confluent/discovery/protocols/ssdp.py +++ b/confluent_server/confluent/discovery/protocols/ssdp.py @@ -382,10 +382,12 @@ def _find_service(service, target): if pi is not None: yield pi -def check_fish(urldata): +def check_fish(urldata, port=443, verifycallback=None): + if not verifycallback: + verifycallback = lambda x: True url, data = urldata try: - wc = webclient.SecureHTTPConnection(_get_svrip(data), 443, verifycallback=lambda x: True) + wc = webclient.SecureHTTPConnection(_get_svrip(data), port, verifycallback=verifycallback) peerinfo = wc.grab_json_response(url) except socket.error: return None diff --git a/confluent_server/confluent/selfservice.py b/confluent_server/confluent/selfservice.py index 687e02a0..195c2f72 100644 --- a/confluent_server/confluent/selfservice.py +++ b/confluent_server/confluent/selfservice.py @@ -19,6 +19,10 @@ import json import os import time import yaml +import confluent.discovery.protocols.ssdp as ssdp +import eventlet +webclient = eventlet.import_patched('pyghmi.util.webclient') + currtz = None keymap = 'us' @@ -154,10 +158,36 @@ def handle_request(env, start_response): reqbody = env['wsgi.input'].read(int(env['CONTENT_LENGTH'])) if env['PATH_INFO'] == '/self/register_discovered': rb = json.loads(reqbody) - addrs = rb.get('addresses', []) - rb['addresses'] = [] - for addr in addrs: - rb['addresses'].append(tuple(addr)) + if not rb.get('path', None): + start_response('400 Bad Requst', []) + yield 'Missing Path' + return + targurl = '/hubble/systems/by-port/{0}/webaccess'.format(rb['path']) + tlsverifier = util.TLSCertVerifier(cfg, nodename, 'pubkeys.tls_hardwaremanager') + wc = webclient.SecureHTTPConnection(nodename, 443, verifycallback=tlsverifier.verify_cert) + relaycreds = cfg.get_node_attributes(nodename, 'secret.*', decrypt=True) + relaycreds = relaycreds.get(nodename, {}) + relayuser = relaycreds.get('secret.hardwaremanagementuser', {}).get('value', None) + relaypass = relaycreds.get('secret.hardwaremanagementpassword', {}).get('value', None) + if not relayuser or not relaypass: + raise Exception('No credentials for {0}'.format(nodename)) + wc.set_basic_credentials(relayuser, relaypass) + wc.request('GET', targurl) + rsp = wc.getresponse() + _ = rsp.read() + if rsp.status == 302: + newurl = rsp.headers['Location'] + newhost, newport = newurl.replace('https://', '').split('/')[0].split(':') + def verify_cert(certificate): + hashval = base64.b64decode(rb['fingerprint']) + if len(hashval) == 48: + return hashlib.sha384(certificate).digest() == hashval + raise Exception('Certificate validation failed') + rb['addresses'] = [(newhost, newport)] + rb['forwarder_url'] = targurl + rb['forwarder_server'] = nodename + rb[''] + ssdp.check_fish(('/DeviceDescription.json', rb), newport, verify_cert) disco.detected(rb) start_response('200 OK', []) yield 'Registered'