Visualising LQL Datasources


Badge

LQL has a ton of Datasources that can be queried in a plethora of ways.

Some of these Datasources are even related to each other.

When faced with the challenge of building a custom LQL Query, I’ve built a little tool that helps you find these Datasources and their relationships in a visual way.

 

You can also search for keywords and highlight the Datasource Neighbors:

 

Hovering over one of the Sources and clićking the link takes you to the respective Datasource documentation.

Since each tenant might have a different set of Datasources available, there is no public Datasource Map available, which is why you’ll need to run a quick python script to create your individual graph.

 

Usage is very simple:

pip install laceworksdk pyvis
python datasource_visualizer.py --profile your-lacework-cli-profile

 

Your browser will open up the Map after a few seconds. It’ll be be a HTML file you can reference whenever you need to look something up.

No need to run the script everytime. This is just needed when datasources change/update.

 

 

You can find the Code here:

"""Modules providing functions for os path, arg parsing, logging, opening a webbrowser,
copying instances, lacework client and pyvis network graph modeling"""
import os
import argparse
import logging
import webbrowser
import copy
from laceworksdk import LaceworkClient
from pyvis.network import Network


class LwDatasources:
"""Class representing a network graph model of Lacework Datasources"""

def __init__(self, args, lw_client):
self.lw_client = lw_client
self.args = args
datasource_data = self.get_datasources()
self.build_graph(datasource_data)

def get_datasources(self):
"""Function to retrieve LQL datasources and their source relationships."""

logging.error("Getting datasources from lw org: %s", self.lw_client.subaccount)

lw_client = copy.deepcopy(self.lw_client)
lw_client.set_subaccount(self.args.subaccount)
datasources_names = []
source_relationships = []

datasources = lw_client.datasources.get()
for item in datasources["data"]:
datasources_names.append(item["name"])
for source_relationship in item["sourceRelationships"]:
source_relationships.append(
(source_relationship["from"], source_relationship["to"])
)

return datasources_names, source_relationships

def build_graph(self, datasource_data):
"""Function that takes datasources and their source relationships
and builds a network graph from that information"""

filename = "lql_datasources_graph.html"
net = Network(
directed=True,
select_menu=True,
bgcolor="#222222",
font_color="white",
layout=True,
height="50vw",
width="100%",
)
# net.show_buttons(filter_=['physics'])
# net.show_buttons(filter_=['nodes'])
# net.show_buttons(filter_=['edges'])
net.set_options(
"""
const options = {
"physics": {
"forceAtlas2Based": {
"springLength": 100
},
"minVelocity": 0.75,
"solver": "forceAtlas2Based",
"timestep": 0.48
}
}
"""
)
for node in datasource_data[0]:
net.add_node(
node,
title=(
"<a href='https://docs.lacework.net/lql/restricted/datasource-metadata/#"
+ str.lower(node)
+ "'>"
+ node
),
)
for relationship in datasource_data[1]:
net.add_edge(*relationship)
logging.info("Building network graph...")
net.show(filename, notebook=False)
webbrowser.open("file://" + os.path.realpath(filename))


def main(args):
"""Main function providing the initial lwclient config and arg parsing."""

if args.debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)

lw_client = LaceworkClient(
account=args.account,
subaccount=args.subaccount,
api_key=args.api_key,
api_secret=args.api_secret,
profile=args.profile,
)

LwDatasources(args, lw_client)


if __name__ == "__main__":
# Set up an argument parser
parser = argparse.ArgumentParser(description="")

parser.add_argument(
"--account",
default=os.environ.get("LW_ACCOUNT", None),
help="The Lacework account to use",
)
parser.add_argument(
"--subaccount",
default=os.environ.get("LW_SUBACCOUNT", None),
help="The Lacework sub-account to use",
)

parser.add_argument(
"--api-key",
dest="api_key",
default=os.environ.get("LW_API_KEY", None),
help="The Lacework API key to use for the source account",
)
parser.add_argument(
"--api-secret",
dest="api_secret",
default=os.environ.get("LW_API_SECRET", None),
help="The Lacework API secret to use for the source account",
)

parser.add_argument(
"-p",
"--profile",
default=os.environ.get("LW_PROFILE", None),
help="The Lacework CLI profile to use for the source account",
)

parser.add_argument(
"--debug",
action="store_true",
default=os.environ.get("LW_DEBUG", False),
help="Enable debug logging",
)
arguments = parser.parse_args()

main(arguments)

 

 

Agent

N/A

Platform

Using Lacework/Operationalizing

Cloud

N/A


0 replies

Be the first to reply!

Reply