import docker import pandas as pd import re def sanitize_id(text): # Erlaubt nur Buchstaben, Zahlen und Unterstriche return re.sub(r'\W|^(?=\d)', '_', text) def get_container_info(): client = docker.from_env() containers = client.containers.list(all=True) data = [] for container in containers: container_info = client.api.inspect_container(container.id) name = container.name labels = container_info.get('Config', {}).get('Labels', {}) watchtower_enabled = labels.get('com.centurylinklabs.watchtower.enable', labels.get('watchtower.enable', 'not set')) networks = container_info.get('NetworkSettings', {}).get('Networks', {}) for net_name, net_data in networks.items(): ip_address = net_data.get('IPAddress', 'N/A') gateway = net_data.get('Gateway', 'N/A') data.append({ 'Container Name': name, 'Watchtower Enabled': watchtower_enabled, 'Network': net_name, 'IP Address': ip_address, 'Gateway': gateway }) return data def save_to_csv(data, filename='docker_container_info.csv'): df = pd.DataFrame(data) df.to_csv(filename, index=False) print(f"[+] Daten erfolgreich in {filename} gespeichert.") def save_to_graphml(data, filename='docker_container_info.graphml'): from xml.etree.ElementTree import Element, SubElement, ElementTree, register_namespace # Nur yEd Namespace registrieren! register_namespace('y', "http://www.yworks.com/xml/graphml") graphml = Element('graphml', xmlns="http://graphml.graphdrawing.org/xmlns") # yEd-Label-Schlüssel key_label = SubElement(graphml, 'key', id="d0", **{ "for": "node", "yfiles.type": "nodegraphics" }) key_watchtower = SubElement(graphml, 'key', id="d1", **{ "for": "node", "attr.name": "Watchtower Enabled", "attr.type": "string" }) graph = SubElement(graphml, 'graph', id="G", edgedefault="undirected") container_labels = {} containers = set() networks = set() for entry in data: cname = entry['Container Name'] containers.add(cname) networks.add(entry['Network']) if cname not in container_labels: container_labels[cname] = {} container_labels[cname]['Watchtower Enabled'] = entry['Watchtower Enabled'] # Star Schema: Netzwerke in der Mitte, Container im Kreis import math # Positioniere Netzwerk-Knoten im Zentrum center_x = 500 center_y = 400 net_radius = 0 # Alle Netzwerke exakt im Zentrum net_positions = {} for idx, n in enumerate(networks): node_id = f"network_{sanitize_id(n)}" node = SubElement(graph, 'node', id=node_id) net_infos = [entry for entry in data if entry['Network'] == n] net_texts = [f"{entry['Container Name']}: IP: {entry['IP Address']}, GW: {entry['Gateway']}" for entry in net_infos] label_text = f"{n}\n" + "\n".join(net_texts) data_elem = SubElement(node, 'data', key="d0") y_shape_node = SubElement(data_elem, '{http://www.yworks.com/xml/graphml}ShapeNode') # Alle Netzwerke im Zentrum geometry = SubElement(y_shape_node, '{http://www.yworks.com/xml/graphml}Geometry', x=str(center_x), y=str(center_y), width="200", height="60") y_node_label = SubElement(y_shape_node, '{http://www.yworks.com/xml/graphml}NodeLabel') y_node_label.text = label_text net_positions[n] = (center_x, center_y) # Container-Knoten im Kreis um das Zentrum container_count = len(containers) radius = 300 angle_step = 2 * math.pi / max(container_count, 1) container_positions = {} for idx, c in enumerate(containers): node_id = f"container_{sanitize_id(c)}" ip_infos = [entry for entry in data if entry['Container Name'] == c] ip_texts = [f"IP: {info['IP Address']}, GW: {info['Gateway']}, Net: {info['Network']}" for info in ip_infos] # Ermittle Watchtower-Status aus com.centurylinklabs.watchtower.enable watchtower_status = "aktiviert" if any( info.get('Watchtower Enabled', '').lower() in ['true', '1', 'yes', 'enabled'] for info in ip_infos ) else "deaktiviert" label_text = f"{c}\nWatchtower: {watchtower_status}\n" + "\n".join(ip_texts) node = SubElement(graph, 'node', id=node_id) data_elem = SubElement(node, 'data', key="d0") y_shape_node = SubElement(data_elem, '{http://www.yworks.com/xml/graphml}ShapeNode') # Kreisförmige Position angle = idx * angle_step x = center_x + radius * math.cos(angle) y = center_y + radius * math.sin(angle) geometry = SubElement(y_shape_node, '{http://www.yworks.com/xml/graphml}Geometry', x=str(x), y=str(y), width="200", height="60") y_node_label = SubElement(y_shape_node, '{http://www.yworks.com/xml/graphml}NodeLabel') y_node_label.text = label_text watchtower_elem = SubElement(node, 'data', key="d1") watchtower_elem.text = container_labels[c]['Watchtower Enabled'] container_positions[c] = (x, y) edge_id = 0 for entry in data: source = f"container_{sanitize_id(entry['Container Name'])}" target = f"network_{sanitize_id(entry['Network'])}" edge = SubElement(graph, 'edge', id=f"e{edge_id}", source=source, target=target) edge_id += 1 tree = ElementTree(graphml) tree.write(filename, encoding='utf-8', xml_declaration=True) print(f"[+] GraphML erfolgreich in {filename} gespeichert.") if __name__ == '__main__': print("[*] Sammle Container-Informationen...") container_data = get_container_info() save_to_csv(container_data) save_to_graphml(container_data)