decompose

module
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2023 License: MIT

README

License Go Version Release FOSSA Status

CI Go Report Card Maintainability Test Coverage Issues

decompose

Reverse-engineering tool for docker environments.

Takes all network connections from your docker containers and exports them as:

type Item struct {
    Name       string              `json:"name"`              // container name
    IsExternal bool                `json:"is_external"`       // this host is external
    Image      *string             `json:"image,omitempty"`   // docker image (if any)
    Meta       *Meta               `json:"meta,omitempty"`    // metadata, see 'metadata'
    Process    *Process            `json:"process,omitempty"` // process info
    Listen     []string            `json:"listen"`            // ports description i.e. '443/tcp'
    Networks   []string            `json:"networks"`          // network names
    Volumes    []*Volume           `json:"volumes"`           // volumes
    Connected  map[string][]string `json:"connected"`         // name -> ports slice
}

type Meta struct {
    Info string   `json:"info"`
    Tags []string `json:"tags"`
}

type Volume struct {
    Type string `json:"type"`
    Src  string `json:"src"`
    Dst  string `json:"dst"`
}

type Process struct {
    Cmd []string `json:"cmd"`
    Env []string `json:"env"`
}

example with full info and metadata filled:

{
    "name": "foo-1",
    "is_external": false,
    "image": "repo/foo:latest",
    "process": {
        "cmd": [
            "foo",
            "-foo-arg"
        ],
        "env": [
            "FOO=1"
        ]
    },
    "meta": {
        "info": "info for foo",
        "tags": ["some"]
    },
    "listen": ["80/tcp"],
    "networks": ["test-net"],
    "volumes": [
        {
            "type": "volume",
            "src": "/var/lib/docker/volumes/foo_1/_data",
            "dst": "/data"
        },
        {
            "type": "bind",
            "src": "/path/to/foo.conf",
            "dst": "/etc/foo.conf"
        }
    ],
    "connected": {
        "bar-1": ["443/tcp"]
    }
}

See stream.json for simple stream example.

metadata format

To enrich output with detailed descriptions, you can provide additional json file, with metadata i.e.:

{
    "foo": {
        "info": "info for foo",
        "tags": ["some"]
    },
    "bar": {
        "info": "info for bar",
        "tags": ["other", "not-foo"]
    }
}

Using this file decompose can enrich output with info and additional tags, for every container that match by name with one of provided keys, like foo-1 or bar1 for this example.

See csv2meta.py for example how to create such json fom csv, and meta.json for metadata sample.

clusterization rules

You can join your services into clusters by exposed ports, with clusterization rules, for example:

[
    {"name": "ingress", "ports": ["80/tcp", "443/tcp"]},
    {"name": "backend", "ports": ["8080-8090/tcp"]},
    {"name": "store", "ports": ["3306/tcp", "5432/tcp"]},
    {"name": "redis", "ports": ["6379/tcp"]},
    {"name": "queue", "ports": ["9092/tcp", "4222/tcp"]}
]

Source: cluster.json

features

  • os-independent, it uses different strategies to get container connections:
    • running on linux as root is the fastest way and it will work with all types of containers (even scratch-based)
    • running as non-root or on non-linux OS will attempt to run netsat inside container, if this fails (i.e. for missing netstat binary), no connections for such container will be gathered
  • produces detailed connections graph with ports
  • fast, scans ~400 containers in around 5 seconds
  • 100% test-coverage

known limitations

  • only established and listen connections are listed

installation

usage

decompose [flags]

possible flags with default values:

  -cluster string
        json file with clusterization rules
  -follow string
        follow only this container by name
  -format string
        output format: dot, json, tree or sdsl for structurizr dsl (default "dot")
  -full
        extract full process info: (cmd, args, env) and volumes info
  -help
        show this help
  -load value
        load json stream, can be used multiple times
  -local
        skip external hosts
  -meta string
        json file with metadata for enrichment
  -no-loops
        remove connection loops (node to itself) from output
  -out string
        output: filename or "-" for stdout (default "-")
  -proto string
        protocol to scan: tcp, udp or all (default "all")
  -silent
        suppress progress messages in stderr
  -skip-env string
        environment variables name(s) to skip from output, case-independent, comma-separated
  -version
        show version

environment variables:

  • DOCKER_HOST - connection uri
  • DOCKER_CERT_PATH - directory path containing key.pem, cert.pm and ca.pem
  • DOCKER_TLS_VERIFY - enable client TLS verification

examples

Get dot file:

decompose > connections.dot

Process json stream:

decompose -format json | jq '{name}'

Get only tcp connections as dot:

decompose -proto tcp > tcp.dot

Save full json stream:

decompose -full -format json > nodes-1.json

Display tree:

decompose -format tree

Merge graphs from json streams, filter by protocol, skip remote hosts and save as dot:

decompose -local -proto tcp -load nodes-1.json -load nodes-2.json > graph-merged.dot

Load json stream, enrich and save as structurizr dsl:

decompose -load nodes-1.json -meta metadata.json -format sdsl > workspace.dsl

example result

Scheme taken from redis-cluster:

svg it may be too heavy to display it with browser, use save image as and open it locally

Steps to reproduce:

git clone https://github.com/s0rg/redis-cluster-compose.git
cd redis-cluster-compose
docker compose up

in other terminal:

decompose | dot -Tsvg > redis-cluster.svg

license

FOSSA Status

Directories

Path Synopsis
cmd
decompose command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL