def login(self, host_spec="", username="", password=""): """ Authenticate with infrastructure via the Skydive analyzer This method will also set the authentication cookie to be used in the future requests :param host_spec: Host IP and port (e.g. 192.168.10.1:8082) :type host_spec: string :param username: Username to use for login :type username: string :param password: Password to use for login :type password: string :return: True on successful authentication, False otherwise """ warnings.warn( "shouldn't use this function anymore ! use connect which handles" "handles authentication directly.", DeprecationWarning ) scheme = "http" if not host_spec: u = urlparse(self.endpoint) host_spec = u.netloc if u.scheme == "wss": scheme = "https" if self.username: username = self.username if self.password: password = self.password auth = Authenticate(host_spec, scheme=scheme, username=username, password=password) try: auth.login() cookie = 'authtok={}'.format(auth.authtok) if self.cookies: self.cookies.append(cookie) else: self.cookies = [cookie, ] return True except Exception: return False
def __init__(self, endpoint, scheme="http", username="", password="", insecure=False, debug=0): self.endpoint = endpoint self.scheme = scheme self.username = username self.password = password self.insecure = insecure self.debug = debug self.auth = Authenticate(endpoint, scheme, username, password, insecure)
def __init__(self, host_id, endpoint, type="", protocol=WSClientDefaultProtocol, username="", password="", cookie=None, sync="", filter="", persistent=True, insecure=False, **kwargs): super(WSClient, self).__init__() self.host_id = host_id self.endpoint = endpoint self.username = username self.password = password if not cookie: self.cookies = None elif isinstance(cookie, list): self.cookies = cookie else: self.cookies = [cookie, ] self.protocol = protocol self.type = type self.filter = filter self.persistent = persistent self.sync = sync self.insecure = insecure self.kwargs = kwargs self.url = urlparse(self.endpoint) scheme = "http" if self.url.scheme == "wss": scheme = "http" self.auth = Authenticate( "%s:%s" % (self.url.hostname, self.url.port), scheme=scheme, username=username, password=password, insecure=insecure) # We MUST initialize the loop here as the WebSocketClientFactory # needs it on init try: self.loop = asyncio.get_event_loop() except RuntimeError: self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop)
class RESTClient: def __init__(self, endpoint, scheme="http", username="", password="", insecure=False, debug=0): self.endpoint = endpoint self.scheme = scheme self.username = username self.password = password self.insecure = insecure self.debug = debug self.auth = Authenticate(endpoint, scheme, username, password, insecure) def request(self, path, method="GET", data=None): if self.username and not self.auth.authenticated: self.auth.login() handlers = [] url = "%s://%s%s" % (self.scheme, self.endpoint, path) handlers.append(request.HTTPHandler(debuglevel=self.debug)) handlers.append(request.HTTPCookieProcessor(self.auth.cookie_jar)) if self.scheme == "https": if self.insecure: context = ssl._create_unverified_context() else: context = ssl._create_default_context() handlers.append(request.HTTPSHandler(debuglevel=self.debug, context=context)) if data is not None: encoded_data = data.encode() else: encoded_data = None opener = request.build_opener(*handlers) headers = {'Content-Type': 'application/json'} req = request.Request(url, data=encoded_data, headers=headers) req.get_method = lambda: method try: resp = opener.open(req) except request.HTTPError as e: self.auth.logout() raise BadRequest(e.read()) data = resp.read() # DEPRECATED: workaround for skydive < 0.17 # See PR #941 if method == "DELETE": return data content_type = resp.headers.get("Content-type").split(";")[0] if content_type == "application/json": return json.loads(data.decode()) return data def lookup(self, gremlin, klass=None): data = json.dumps( {"GremlinQuery": gremlin} ) objs = self.request("/api/topology", method="POST", data=data) if klass: return [klass.from_object(o) for o in objs] return objs def lookup_nodes(self, gremlin): return self.lookup(gremlin, Node) def lookup_edges(self, gremlin): return self.lookup(gremlin, Edge) def capture_create(self, query): data = json.dumps( {"GremlinQuery": query} ) return self.request("/api/capture", method="POST", data=data) def capture_list(self): return self.request("/api/capture") def capture_delete(self, capture_id): path = "/api/capture/%s" % capture_id return self.request(path, method="DELETE")
class WSClient(WebSocketClientProtocol): def __init__(self, host_id, endpoint, type="", protocol=WSClientDefaultProtocol, username="", password="", cookie=None, sync="", filter="", persistent=True, insecure=False, **kwargs): super(WSClient, self).__init__() self.host_id = host_id self.endpoint = endpoint self.username = username self.password = password if not cookie: self.cookies = None elif isinstance(cookie, list): self.cookies = cookie else: self.cookies = [cookie, ] self.protocol = protocol self.type = type self.filter = filter self.persistent = persistent self.sync = sync self.insecure = insecure self.kwargs = kwargs self.url = urlparse(self.endpoint) scheme = "http" if self.url.scheme == "wss": scheme = "http" self.auth = Authenticate( "%s:%s" % (self.url.hostname, self.url.port), scheme=scheme, username=username, password=password, insecure=insecure) # We MUST initialize the loop here as the WebSocketClientFactory # needs it on init try: self.loop = asyncio.get_event_loop() except RuntimeError: self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) def connect(self): factory = WebSocketClientFactory(self.endpoint) factory.protocol = self.protocol factory.client = self factory.kwargs = self.kwargs factory.headers["X-Host-ID"] = self.host_id factory.headers["X-Client-Type"] = self.type factory.headers["X-Client-Protocol"] = "json" if self.persistent: factory.headers["X-Persistence-Policy"] = "Persistent" else: factory.headers["X-Persistence-Policy"] = "DeleteOnDisconnect" if self.username: if self.auth.login(): cookie = 'authtok={}'.format(self.auth.authtok) if self.cookies: self.cookies.append(cookie) else: self.cookies = [cookie, ] if self.filter: factory.headers["X-Gremlin-Filter"] = self.filter if self.cookies: factory.headers['Cookie'] = ';'.join(self.cookies) context = None if self.url.scheme == "wss": if self.insecure: context = ssl._create_unverified_context() else: context = ssl._create_default_context() coro = self.loop.create_connection(factory, self.url.hostname, self.url.port, ssl=context) (transport, protocol) = self.loop.run_until_complete(coro) LOG.debug('transport, protocol: %r, %r', transport, protocol) def login(self, host_spec="", username="", password=""): """ Authenticate with infrastructure via the Skydive analyzer This method will also set the authentication cookie to be used in the future requests :param host_spec: Host IP and port (e.g. 192.168.10.1:8082) :type host_spec: string :param username: Username to use for login :type username: string :param password: Password to use for login :type password: string :return: True on successful authentication, False otherwise """ warnings.warn( "shouldn't use this function anymore ! use connect which handles" "handles authentication directly.", DeprecationWarning ) scheme = "http" if not host_spec: u = urlparse(self.endpoint) host_spec = u.netloc if u.scheme == "wss": scheme = "https" if self.username: username = self.username if self.password: password = self.password auth = Authenticate(host_spec, scheme=scheme, username=username, password=password) try: auth.login() cookie = 'authtok={}'.format(auth.authtok) if self.cookies: self.cookies.append(cookie) else: self.cookies = [cookie, ] return True except Exception: return False def start(self): try: self.loop.run_forever() except KeyboardInterrupt: self.loop.close() finally: pass def stop(self): self.loop.stop()
class WSClient(WebSocketClientProtocol): def __init__(self, host_id, endpoint, protocol=WSClientDefaultProtocol, username="", password="", cookie=None, sync="", filter="", persistent=True, insecure=False, type="skydive-python-client", **kwargs): super(WSClient, self).__init__() self.host_id = host_id self.endpoint = endpoint self.username = username self.password = password if not cookie: self.cookies = None elif isinstance(cookie, list): self.cookies = cookie elif isinstance(cookie, dict): self.cookies = [] for k, v in cookie.items(): self.cookies.append("{}={}".format(k, v)) else: self.cookies = [ cookie, ] self.protocol = protocol self.type = type self.filter = filter self.persistent = persistent self.sync = sync self.insecure = insecure self.kwargs = kwargs self.url = urlparse(self.endpoint) scheme = "http" if self.url.scheme == "wss": scheme = "http" self.auth = Authenticate("%s:%s" % (self.url.hostname, self.url.port), scheme=scheme, username=username, password=password, insecure=insecure) # We MUST initialize the loop here as the WebSocketClientFactory # needs it on init try: self.loop = asyncio.get_event_loop() except RuntimeError: self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) def connect(self): factory = WebSocketClientFactory(self.endpoint) factory.protocol = self.protocol factory.client = self factory.kwargs = self.kwargs factory.headers["X-Host-ID"] = self.host_id factory.headers["X-Client-Type"] = self.type factory.headers["X-Client-Protocol"] = "json" if self.persistent: factory.headers["X-Persistence-Policy"] = "Persistent" else: factory.headers["X-Persistence-Policy"] = "DeleteOnDisconnect" if self.username: if self.auth.login(): cookie = 'authtok={}'.format(self.auth.authtok) if self.cookies: self.cookies.append(cookie) else: self.cookies = [ cookie, ] if self.filter: factory.headers["X-Gremlin-Filter"] = self.filter if self.cookies: factory.headers['Cookie'] = ';'.join(self.cookies) context = None if self.url.scheme == "wss": if self.insecure: context = ssl._create_unverified_context() else: context = ssl._create_default_context() coro = self.loop.create_connection(factory, self.url.hostname, self.url.port, ssl=context) (transport, protocol) = self.loop.run_until_complete(coro) LOG.debug('transport, protocol: %r, %r', transport, protocol) def login(self, host_spec="", username="", password=""): """ Authenticate with infrastructure via the Skydive analyzer This method will also set the authentication cookie to be used in the future requests :param host_spec: Host IP and port (e.g. 192.168.10.1:8082) :type host_spec: string :param username: Username to use for login :type username: string :param password: Password to use for login :type password: string :return: True on successful authentication, False otherwise """ warnings.warn( "shouldn't use this function anymore ! use connect which handles" "handles authentication directly.", DeprecationWarning) scheme = "http" if not host_spec: u = urlparse(self.endpoint) host_spec = u.netloc if u.scheme == "wss": scheme = "https" if self.username: username = self.username if self.password: password = self.password auth = Authenticate(host_spec, scheme=scheme, username=username, password=password) try: auth.login() cookie = 'authtok={}'.format(auth.authtok) if self.cookies: self.cookies.append(cookie) else: self.cookies = [ cookie, ] return True except Exception: return False def start(self): try: self.loop.run_forever() except KeyboardInterrupt: self.loop.close() finally: pass def stop(self): self.loop.stop()
class RESTClient: INJECTION_PATH = "/api/injectpacket" def __init__(self, endpoint, scheme="http", username="", password="", cookies={}, insecure=False, debug=0): self.endpoint = endpoint self.scheme = scheme self.username = username self.password = password self.insecure = insecure self.debug = debug self.cookies = cookies self.auth = Authenticate(endpoint, scheme, username, password, cookies, insecure) def request(self, path, method="GET", data=None): if self.username and not self.auth.authenticated: self.auth.login() handlers = [] url = "%s://%s%s" % (self.scheme, self.endpoint, path) handlers.append(request.HTTPHandler(debuglevel=self.debug)) handlers.append(request.HTTPCookieProcessor(self.auth.cookie_jar)) if self.scheme == "https": if self.insecure: context = ssl._create_unverified_context() else: context = ssl.create_default_context() handlers.append( request.HTTPSHandler(debuglevel=self.debug, context=context)) if data is not None: encoded_data = data.encode() else: encoded_data = None opener = request.build_opener(*handlers) for k, v in self.cookies.items(): opener.append = (k, v) headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' } req = request.Request(url, data=encoded_data, headers=headers) req.get_method = lambda: method try: resp = opener.open(req) except request.HTTPError as e: self.auth.logout() raise BadRequest(e.read()) data = resp.read() # DEPRECATED: workaround for skydive < 0.17 # See PR #941 if method == "DELETE": return data content_type = resp.headers.get("Content-type").split(";")[0] if content_type == "application/json": return json.loads(data.decode()) return data def lookup(self, gremlin, klass=None): data = json.dumps({"GremlinQuery": gremlin}) objs = self.request("/api/topology", method="POST", data=data) if klass: return [klass.from_object(o) for o in objs] return objs def lookup_nodes(self, gremlin): return self.lookup(gremlin, Node) def lookup_edges(self, gremlin): return self.lookup(gremlin, Edge) def capture_create(self, query, name="", description="", extra_tcp_metric=False, ip_defrag=False, reassemble_tcp=False, layer_key_mode="L2", bpf_filter="", capture_type="", port=0, raw_pkt_limit=0, header_size=0, target="", target_type="", polling_interval=10, sampling_rate=1): data = { "GremlinQuery": query, "LayerKeyMode": layer_key_mode, "PollingInterval": polling_interval, "SamplingRate": sampling_rate, } if name: data["Name"] = name if description: data["Description"] = description if extra_tcp_metric: data["ExtraTCPMetric"] = True if ip_defrag: data["IPDefrag"] = True if reassemble_tcp: data["ReassembleTCP"] = True if bpf_filter: data["BPFFilter"] = bpf_filter if capture_type: data["Type"] = capture_type if raw_pkt_limit: data["RawPacketLimit"] = raw_pkt_limit if header_size: data["HeaderSize"] = header_size if port: data["Port"] = port if target: data["Target"] = target if target_type: data["TargetType"] = target_type c = self.request("/api/capture", method="POST", data=json.dumps(data)) return Capture.from_object(c) def capture_list(self): objs = self.request("/api/capture") return [Capture.from_object(o) for o in objs.values()] def capture_delete(self, capture_id): path = "/api/capture/%s" % capture_id return self.request(path, method="DELETE") def alert_create(self, action, expression, trigger="graph"): data = json.dumps({ "Action": action, "Expression": expression, "Trigger": trigger }) a = self.request("/api/alert", method="POST", data=data) return Alert.from_object(a) def alert_list(self): objs = self.request("/api/alert") return [Alert.from_object(o) for o in objs.values()] def alert_delete(self, alert_id): path = "/api/alert/%s" % alert_id return self.request(path, method="DELETE") def noderule_create(self, action, metadata=None, query=""): data = json.dumps({ "Action": action, "Metadata": metadata, "Query": query }) r = self.request("/api/noderule", method="POST", data=data) return NodeRule.from_object(r) def noderule_list(self): objs = self.request("/api/noderule") return [NodeRule.from_object(o) for o in objs.values()] def noderule_delete(self, rule_id): path = "/api/noderule/%s" % rule_id return self.request(path, method="DELETE") def edgerule_create(self, src, dst, metadata): data = json.dumps({"Src": src, "Dst": dst, "Metadata": metadata}) r = self.request("/api/edgerule", method="POST", data=data) return EdgeRule.from_object(r) def edgerule_list(self): objs = self.request("/api/edgerule") return [EdgeRule.from_object(o) for o in objs.values()] def edgerule_delete(self, rule_id): path = "/api/edgerule/%s" % rule_id self.request(path, method="DELETE") def node_create(self, node_id=None, host=None, metadata=None): now = int(time() * 1000) if not node_id: node_id = str(uuid4()) if not host: host = gethostname() data = json.dumps({ "ID": node_id, "CreatedAt": now, "UpdatedAt": now, "Host": host, "Metadata": metadata, "Revision": 1 }) r = self.request("/api/node", method="POST", data=data) return Node.from_object(r) def node_update(self, node_id=None, patches=[]): data = json.dumps(patches) path = "/api/node/%s" % node_id r = self.request(path, method="PATCH", data=data) return Node.from_object(r) def node_list(self): objs = self.request("/api/node") return [Node.from_object(o) for o in objs.values()] def node_delete(self, node_id): path = "/api/node/%s" % node_id return self.request(path, method="DELETE") def edge_create(self, parent_id, child_id, edge_id=None, host=None, metadata=None): now = int(time() * 1000) if not edge_id: edge_id = str(uuid4()) if not host: host = gethostname() data = json.dumps({ "ID": edge_id, "CreatedAt": now, "UpdatedAt": now, "Host": host, "Parent": parent_id, "Child": child_id, "Metadata": metadata }) r = self.request("/api/edge", method="POST", data=data) return Edge.from_object(r) def edge_update(self, edge_id=None, patches=[]): data = json.dumps(patches) path = "/api/edge/%s" % edge_id r = self.request(path, method="PATCH", data=data) return Edge.from_object(r) def edge_list(self): objs = self.request("/api/edge") return [Edge.from_object(o) for o in objs.values()] def edge_delete(self, edge_id): path = "/api/edge/%s" % edge_id self.request(path, method="DELETE") def injection_create(self, src_query="", dst_query="", type="icmp4", payload="", interval=1000, src_ip="", dst_ip="", src_mac="", dst_mac="", count=1, icmp_id=0, src_port=0, dst_port=0, increment=False, ttl=64): data = json.dumps({ "Src": src_query, "Dst": dst_query, "SrcPort": src_port, "DstPort": dst_port, "SrcIP": src_ip, "DstIP": dst_ip, "SrcMAC": src_mac, "DstMAC": dst_mac, "Type": type, "Count": count, "ICMPID": icmp_id, "Interval": interval, "Payload": payload, "Increment": increment, "TTL": ttl }) r = self.request(self.INJECTION_PATH, method="POST", data=data) return PacketInjection.from_object(r) def injection_delete(self, injection_id): path = self.INJECTION_PATH + "/" + injection_id return self.request(path, method="DELETE") def injection_list(self): objs = self.request(self.INJECTION_PATH) return [PacketInjection.from_object(o) for o in objs.values()]
class RESTClient: def __init__(self, endpoint, scheme="http", username="", password="", insecure=False, debug=0): self.endpoint = endpoint self.scheme = scheme self.username = username self.password = password self.insecure = insecure self.debug = debug self.auth = Authenticate(endpoint, scheme, username, password, insecure) def request(self, path, method="GET", data=None): if self.username and not self.auth.authenticated: self.auth.login() handlers = [] url = "%s://%s%s" % (self.scheme, self.endpoint, path) handlers.append(request.HTTPHandler(debuglevel=self.debug)) handlers.append(request.HTTPCookieProcessor(self.auth.cookie_jar)) if self.scheme == "https": if self.insecure: context = ssl._create_unverified_context() else: context = ssl._create_default_context() handlers.append( request.HTTPSHandler(debuglevel=self.debug, context=context)) if data is not None: encoded_data = data.encode() else: encoded_data = None opener = request.build_opener(*handlers) headers = {'Content-Type': 'application/json'} req = request.Request(url, data=encoded_data, headers=headers) req.get_method = lambda: method try: resp = opener.open(req) except request.HTTPError as e: self.auth.logout() raise BadRequest(e.read()) data = resp.read() # DEPRECATED: workaround for skydive < 0.17 # See PR #941 if method == "DELETE": return data content_type = resp.headers.get("Content-type").split(";")[0] if content_type == "application/json": return json.loads(data.decode()) return data def lookup(self, gremlin, klass=None): data = json.dumps({"GremlinQuery": gremlin}) objs = self.request("/api/topology", method="POST", data=data) if klass: return [klass.from_object(o) for o in objs] return objs def lookup_nodes(self, gremlin): return self.lookup(gremlin, Node) def lookup_edges(self, gremlin): return self.lookup(gremlin, Edge) def capture_create(self, query): data = json.dumps({"GremlinQuery": query}) return self.request("/api/capture", method="POST", data=data) def capture_list(self): return self.request("/api/capture") def capture_delete(self, capture_id): path = "/api/capture/%s" % capture_id return self.request(path, method="DELETE")
class RESTClient: def __init__(self, endpoint, scheme="http", username="", password="", cookies={}, insecure=False, debug=0): self.endpoint = endpoint self.scheme = scheme self.username = username self.password = password self.insecure = insecure self.debug = debug self.cookies = cookies self.auth = Authenticate(endpoint, scheme, username, password, cookies, insecure) def request(self, path, method="GET", data=None): if self.username and not self.auth.authenticated: self.auth.login() handlers = [] url = "%s://%s%s" % (self.scheme, self.endpoint, path) handlers.append(request.HTTPHandler(debuglevel=self.debug)) handlers.append(request.HTTPCookieProcessor(self.auth.cookie_jar)) if self.scheme == "https": if self.insecure: context = ssl._create_unverified_context() else: context = ssl._create_default_context() handlers.append( request.HTTPSHandler(debuglevel=self.debug, context=context)) if data is not None: encoded_data = data.encode() else: encoded_data = None opener = request.build_opener(*handlers) for k, v in self.cookies.items(): opener.append = (k, v) headers = {'Content-Type': 'application/json'} req = request.Request(url, data=encoded_data, headers=headers) req.get_method = lambda: method try: resp = opener.open(req) except request.HTTPError as e: self.auth.logout() raise BadRequest(e.read()) data = resp.read() # DEPRECATED: workaround for skydive < 0.17 # See PR #941 if method == "DELETE": return data content_type = resp.headers.get("Content-type").split(";")[0] if content_type == "application/json": return json.loads(data.decode()) return data def lookup(self, gremlin, klass=None): data = json.dumps({"GremlinQuery": gremlin}) objs = self.request("/api/topology", method="POST", data=data) if klass: return [klass.from_object(o) for o in objs] return objs def lookup_nodes(self, gremlin): return self.lookup(gremlin, Node) def lookup_edges(self, gremlin): return self.lookup(gremlin, Edge) def capture_create(self, query, name="", description="", extra_tcp_metric=False, ip_defrag=False, reassemble_tcp=False, layer_key_mode="L2"): data = { "GremlinQuery": query, "LayerKeyMode": layer_key_mode, } if name: data["Name"] = name if description: data["Description"] = description if extra_tcp_metric: data["ExtraTCPMetric"] = True if ip_defrag: data["IPDefrag"] = True if reassemble_tcp: data["ReassembleTCP"] = True c = self.request("/api/capture", method="POST", data=json.dumps(data)) return Capture.from_object(c) def capture_list(self): objs = self.request("/api/capture") return [Capture.from_object(o) for o in objs.values()] def capture_delete(self, capture_id): path = "/api/capture/%s" % capture_id return self.request(path, method="DELETE") def alert_create(self, action, expression, trigger="graph"): data = json.dumps({ "Action": action, "Expression": expression, "Trigger": trigger }) a = self.request("/api/alert", method="POST", data=data) return Alert.from_object(a) def alert_list(self): objs = self.request("/api/alert") return [Alert.from_object(o) for o in objs.values()] def alert_delete(self, alert_id): path = "/api/alert/%s" % alert_id return self.request(path, method="DELETE") def noderule_create(self, action, metadata=None, query=""): data = json.dumps({ "Action": action, "Metadata": metadata, "Query": query }) r = self.request("/api/noderule", method="POST", data=data) return NodeRule.from_object(r) def noderule_list(self): objs = self.request("/api/noderule") return [NodeRule.from_object(o) for o in objs.values()] def noderule_delete(self, rule_id): path = "/api/noderule/%s" % rule_id return self.request(path, method="DELETE") def edgerule_create(self, src, dst, metadata): data = json.dumps({"Src": src, "Dst": dst, "Metadata": metadata}) r = self.request("/api/edgerule", method="POST", data=data) return EdgeRule.from_object(r) def edgerule_list(self): objs = self.request("/api/edgerule") return [EdgeRule.from_object(o) for o in objs.values()] def edgerule_delete(self, rule_id): path = "/api/edgerule/%s" % rule_id self.request(path, method="DELETE")