def get_paths_info(self, dst_isd_as): lib_sciond.init(get_sciond_api_addr(self.addr)) paths = [] for reply in lib_sciond.get_paths(dst_isd_as): paths.append((reply.path().fwd_path(), reply.first_hop().ipv4(), reply.first_hop().p.port)) return paths
def __init__(self, server_id, conf_dir): """ :param str server_id: server identifier. :param str conf_dir: configuration directory. """ super().__init__(server_id, conf_dir) self.cc_requests = RequestHandler.start( "CC Requests", self._check_cc, self._fetch_cc, self._reply_cc, ) self.trc_requests = RequestHandler.start( "TRC Requests", self._check_trc, self._fetch_trc, self._reply_trc, ) self.drkey_protocol_requests = RequestHandler.start( "DRKey Requests", self._check_drkey, self._fetch_drkey, self._reply_proto_drkey, ) self.CTRL_PLD_CLASS_MAP = { PayloadClass.CERT: { CertMgmtType.CERT_CHAIN_REQ: self.process_cert_chain_request, CertMgmtType.CERT_CHAIN_REPLY: self.process_cert_chain_reply, CertMgmtType.TRC_REQ: self.process_trc_request, CertMgmtType.TRC_REPLY: self.process_trc_reply, }, PayloadClass.DRKEY: { DRKeyMgmtType.FIRST_ORDER_REQUEST: self.process_drkey_request, DRKeyMgmtType.FIRST_ORDER_REPLY: self.process_drkey_reply, }, } zkid = ZkID.from_values(self.addr.isd_as, self.id, [(self.addr.host, self._port)]).pack() self.zk = Zookeeper(self.topology.isd_as, CERTIFICATE_SERVICE, zkid, self.topology.zookeepers) self.zk.retry("Joining party", self.zk.party_setup) self.trc_cache = ZkSharedCache(self.zk, self.ZK_TRC_CACHE_PATH, self._cached_trcs_handler) self.cc_cache = ZkSharedCache(self.zk, self.ZK_CC_CACHE_PATH, self._cached_certs_handler) self.drkey_cache = ZkSharedCache(self.zk, self.ZK_DRKEY_PATH, self._cached_drkeys_handler) lib_sciond.init( os.path.join(SCIOND_API_SOCKDIR, "sd%s.sock" % self.addr.isd_as)) self.signing_key = get_sig_key(self.conf_dir) self.private_key = get_enc_key(self.conf_dir) self.public_key = self.private_key.public_key self.drkey_secrets = ExpiringDict(DRKEY_MAX_SV, DRKEY_MAX_TTL) self.first_order_drkeys = ExpiringDict(DRKEY_MAX_KEYS, DRKEY_MAX_TTL)
def get_path(self, dst_isd_as): lib_sciond.init(get_sciond_api_addr(self.addr)) replies = lib_sciond.get_paths(dst_isd_as) if not replies: return None # TODO(PSz): Very hacky to avoid changing scion_elem and/or giving topo files for # every element. path = replies[0].path().fwd_path() ifid = path.get_fwd_if() if ifid not in self.ifid2br: br = Element() br.addr = replies[0].first_hop().ipv4() br.port = replies[0].first_hop().p.port self.ifid2br[ifid] = br return path
def __init__(self, finished, addr): # We need the lib sciond here already. connector = lib_sciond.init(get_sciond_api_addr(addr)) cs_info = lib_sciond.get_service_info( [ServiceType.CS], connector=connector)[ServiceType.CS] cs = cs_info.host_info(0) cs_addr = SCIONAddr.from_values(addr.isd_as, cs.ipv4() or cs.ipv6()) self.cert_done = False super().__init__("", finished, addr, cs_addr, cs.p.port)
def __init__(self, data, finished, addr, timeout=1.0, api_addr=None): self.api_addr = api_addr or get_sciond_api_addr(addr) self.data = data self.finished = finished self.addr = addr self._timeout = timeout self.sock = self._create_socket(addr) assert self.sock self.success = None self._connector = lib_sciond.init(self.api_addr)
def print_as_viewer_info(addr): ''' Attempt sciond connection if needed, and print requested AS data. :param addr: Optional IP Address for sciond socket binding when not localhost. ''' try: # init connection to sciond conf_dir = "%s/%s/ISD%s/AS%s/endhost" % ( SCION_ROOT, GEN_PATH, s_isd_as.isd_str(), s_isd_as.as_file_fmt()) sock_file = get_default_sciond_path(s_isd_as) if not pathlib.Path(sock_file).exists(): sock_file = get_default_sciond_path(None) connector[s_isd_as] = lib_sciond.init(sock_file) logging.info(connector[s_isd_as]._api_addr) try: # test if sciond is already running for this AS logging.info("Starting sciond at %s" % sock_file) lib_sciond.get_as_info(connector=connector[s_isd_as]) except (SCIONDResponseError) as err: logging.error("%s: %s" % (err.__class__.__name__, err)) return except (SCIONDConnectionError, FileNotFoundError) as err: logging.warning("%s: %s" % (err.__class__.__name__, err)) # need to launch sciond, wait for uptime launch_sciond(sock_file, conf_dir, addr, s_isd_as) if args.t: # as topology print_as_topology(s_isd_as, connector) if args.p: # announced paths print_paths(s_isd_as, d_isd_as, connector) if args.c: # config print_yml(os.path.join(conf_dir, AS_CONF_FILE)) if args.pp: # path policy print_yml(os.path.join(conf_dir, PATH_POLICY_FILE)) if args.trc: # TRC print_json_files(findCerts(conf_dir, ".trc")) if args.crt: # cert chain print_json_files(findCerts(conf_dir, ".crt")) if args.s: # segments print_segments_summary(s_isd_as, connector) except (SCIONBaseError, AttributeError) as err: logging.error("%s: %s" % (err.__class__.__name__, err))
def index(request): ''' Main index handler for index.html for main visualization page. Validates parameters, request scion data, returns formatted response. :param request: HTML request object containing url parameters. ''' p = {} # return param dictionary p['tab'] = set_param(request, 'tab', 'tab-pathtopo') p['data'] = set_param(request, 'data', 'sdapi') p['addr'] = set_param(request, 'addr', '') p['src'] = set_param(request, 'src', '') p['dst'] = set_param(request, 'dst', '') p['mp'] = set_param(request, 'mp', '5') p['err'] = '' if (p['src'] == '' and p['dst'] == ''): # use endhost gen/ia if no host specified if (p['src'] == ''): ia_file = "%s/%s/ia" % (SCION_ROOT, GEN_PATH) try: with open(ia_file, 'r') as fin: # load and reformat p['src'] = str(ISD_AS(fin.read().strip())) except (FileNotFoundError) as err: logging.warning("%s: %s" % (err.__class__.__name__, err)) return fmt_err(request, p) s_isd_as = ISD_AS(p['src']) d_isd_as = ISD_AS(p['dst']) p['src'], p['dst'] = str(s_isd_as), str(d_isd_as) # reformat csegs = dsegs = usegs = [] paths = '' logging.info("Requesting sciond data from %s to %s" % (s_isd_as, d_isd_as)) conf_dir = "%s/%s/ISD%s/AS%s/endhost" % ( SCION_ROOT, GEN_PATH, s_isd_as.isd_str(), s_isd_as.as_file_fmt()) sock_file = get_default_sciond_path(s_isd_as) if not pathlib.Path(sock_file).exists(): sock_file = get_default_sciond_path(None) try: if (p['data'] == 'sdapi'): connector[s_isd_as] = lib_sciond.init(sock_file) logging.info(connector[s_isd_as]._api_addr) try: # test if sciond is already running for this AS logging.info("Testing sciond at %s" % sock_file) lib_sciond.get_as_info(connector=connector[s_isd_as]) except (SCIONDResponseError) as err: p['err'] = "%s: %s" % (err.__class__.__name__, err) return fmt_err(request, p) except (SCIONDConnectionError, FileNotFoundError) as err: logging.warning("%s: %s" % (err.__class__.__name__, err)) # need to launch sciond, wait for uptime launch_sciond(sock_file, conf_dir, p['addr'], s_isd_as) if (p['dst'] != ''): # PATHS try: # get paths and keep segments flags = lib_sciond.PathRequestFlags(flush=False, sibra=False) paths = lib_sciond.get_paths(d_isd_as, max_paths=int(p['mp']), flags=flags, connector=connector[s_isd_as]) csegs = lib_sciond.get_segtype_hops( PST.CORE, connector=connector[s_isd_as]) dsegs = lib_sciond.get_segtype_hops( PST.DOWN, connector=connector[s_isd_as]) usegs = lib_sciond.get_segtype_hops( PST.UP, connector=connector[s_isd_as]) # refresh old segments for next call flags = lib_sciond.PathRequestFlags(flush=True, sibra=False) lib_sciond.get_paths(d_isd_as, max_paths=int(p['mp']), flags=flags, connector=connector[s_isd_as]) except (SCIONDResponseError, SCIONDConnectionError, AttributeError) as err: # AttributeError handles backward-compatability logging.error("%s: %s" % (err.__class__.__name__, err)) p['err'] = str(err) p['json_as_topo'] = json.dumps( get_json_as_topology_sciond(connector[s_isd_as], paths)) p['json_trc'] = ("TRC information for sciond not yet implemented.") p['json_crt'] = ( "Certificate information for sciond not yet implemented.") elif (p['data'] == 'file'): t = Topology.from_file(os.path.join(conf_dir, TOPO_FILE)) topo = organize_topo(t) p['json_as_topo'] = json.dumps(get_json_as_topology(t, topo)) p['json_trc'] = html_jsonfile(findCerts(conf_dir, ".trc")) p['json_crt'] = html_jsonfile(findCerts(conf_dir, ".crt")) p['path_info'] = get_as_view_html(paths, csegs, usegs, dsegs) p['json_path_topo'] = json.dumps( get_json_path_segs(paths, csegs, usegs, dsegs)) p['json_seg_topo'] = json.dumps( get_json_all_segments(csegs, usegs, dsegs)) p['json_paths'] = json.dumps(get_json_paths(paths)) except (SCIONBaseError) as err: p['err'] = "%s: %s" % (err.__class__.__name__, err) return fmt_err(request, p) return render(request, 'asviz/index.html', p)
def __init__(self, server_id, conf_dir, public=None, bind=None, spki_cache_dir=GEN_CACHE_PATH, prom_export=None): """ :param str server_id: server identifier. :param str conf_dir: configuration directory. :param list public: (host_addr, port) of the element's public address (i.e. the address visible to other network elements). :param list bind: (host_addr, port) of the element's bind address, if any (i.e. the address the element uses to identify itself to the local operating system, if it differs from the public address due to NAT). :param str spki_cache_dir: Path for caching TRCs and certificate chains. :param str prom_export: String of the form 'addr:port' specifying the prometheus endpoint. If no string is provided, no metrics are exported. """ self.id = server_id self.conf_dir = conf_dir self.ifid2br = {} self.topology = Topology.from_file( os.path.join(self.conf_dir, TOPO_FILE)) # Labels attached to every exported metric. self._labels = {"server_id": self.id, "isd_as": str(self.topology.isd_as)} # Must be over-ridden by child classes: self.CTRL_PLD_CLASS_MAP = {} self.SCMP_PLD_CLASS_MAP = {} self.public = public self.bind = bind if self.SERVICE_TYPE: own_config = self.topology.get_own_config(self.SERVICE_TYPE, server_id) if public is None: self.public = own_config.public if bind is None: self.bind = own_config.bind self.init_ifid2br() self.trust_store = TrustStore(self.conf_dir, spki_cache_dir, self.id, self._labels) self.total_dropped = 0 self._core_ases = defaultdict(list) # Mapping ISD_ID->list of core ASes self.init_core_ases() self.run_flag = threading.Event() self.run_flag.set() self.stopped_flag = threading.Event() self.stopped_flag.clear() self._in_buf = queue.Queue(MAX_QUEUE) self._socks = SocketMgr() self._startup = time.time() if self.USE_TCP: self._DefaultMeta = TCPMetadata else: self._DefaultMeta = UDPMetadata self.unverified_segs = ExpiringDict(500, 60 * 60) self.unv_segs_lock = threading.RLock() self.requested_trcs = {} self.req_trcs_lock = threading.Lock() self.requested_certs = {} self.req_certs_lock = threading.Lock() # TODO(jonghoonkwon): Fix me to setup sockets for multiple public addresses host_addr, self._port = self.public[0] self.addr = SCIONAddr.from_values(self.topology.isd_as, host_addr) if prom_export: self._export_metrics(prom_export) self._init_metrics() self._setup_sockets(True) lib_sciond.init(os.path.join(SCIOND_API_SOCKDIR, "sd%s.sock" % self.addr.isd_as))