cve: exclude the collector's own container from the scan (+ SOC_EXCLUDE_IMAGES)
Build and push soc-collector / build (push) Successful in 5s
Build and push soc-collector / build (push) Successful in 5s
This commit is contained in:
@@ -61,12 +61,15 @@ enable what you give it.
|
|||||||
| `SOC_TITLE` | | `Security scan — <slug>` | the report's title |
|
| `SOC_TITLE` | | `Security scan — <slug>` | the report's title |
|
||||||
| `SOC_VISIBILITY` | | `private` | `private` or `authenticated` |
|
| `SOC_VISIBILITY` | | `private` | `private` or `authenticated` |
|
||||||
| `SOC_TAGS` | | `collector` | extra report tags |
|
| `SOC_TAGS` | | `collector` | extra report tags |
|
||||||
|
| `SOC_EXCLUDE_IMAGES` | | — | comma-separated substrings; running images matching any are skipped by the `cve` source |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- **Docker socket** is mounted **read-only** (`:ro`) and is only used to *list* running
|
- **Docker socket** is mounted **read-only** (`:ro`) and is only used to *list* running
|
||||||
containers and *inspect* their config. For extra isolation, point it at a scoped
|
containers and *inspect* their config. For extra isolation, point it at a scoped
|
||||||
socket-proxy instead of the raw socket.
|
socket-proxy instead of the raw socket.
|
||||||
|
- The `cve` source **skips the collector's own container**, so the scanner never reports
|
||||||
|
on itself. Use `SOC_EXCLUDE_IMAGES` to drop any other images you don't want scanned.
|
||||||
- The collector is **pure-stdlib Python**; the image just adds `nmap` and `trivy`.
|
- The collector is **pure-stdlib Python**; the image just adds `nmap` and `trivy`.
|
||||||
- Multi-server: run one container per server with a distinct `SOC_SLUG` — one report each.
|
- Multi-server: run one container per server with a distinct `SOC_SLUG` — one report each.
|
||||||
|
|
||||||
|
|||||||
+37
-1
@@ -13,6 +13,9 @@ that you can apply it. For an image you don't build and already run :latest of,
|
|||||||
explicit, and actionable findings sort above the can't-do-anything ones.
|
explicit, and actionable findings sort above the can't-do-anything ones.
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from soc import finding
|
from soc import finding
|
||||||
@@ -23,12 +26,45 @@ OWN_PREFIX = "git.skui.io/"
|
|||||||
STATUS_RANK = {"yours": 0, "update": 1, "upstream": 2}
|
STATUS_RANK = {"yours": 0, "update": 1, "upstream": 2}
|
||||||
|
|
||||||
|
|
||||||
|
def _own_container_id():
|
||||||
|
"""The collector's own container id, so we don't scan ourselves.
|
||||||
|
|
||||||
|
/proc carries the full id regardless of `--hostname`; fall back to the
|
||||||
|
hostname (== the short container id by Docker default). Empty string when
|
||||||
|
not running in a container (then nothing is excluded)."""
|
||||||
|
try:
|
||||||
|
with open("/proc/self/mountinfo") as fh: # …/containers/<id>/{hostname,hosts}
|
||||||
|
m = re.search(r"/containers/([0-9a-f]{64})/", fh.read())
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
with open("/proc/self/cgroup") as fh: # cgroup v1: …/docker/<id>
|
||||||
|
m = re.search(r"docker[-/]([0-9a-f]{64})", fh.read())
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
return socket.gethostname().strip()
|
||||||
|
except Exception:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def _running_images():
|
def _running_images():
|
||||||
conts = _docker.get("/containers/json") or []
|
conts = _docker.get("/containers/json") or []
|
||||||
|
self_id = _own_container_id()
|
||||||
|
# optional extra exclusions: SOC_EXCLUDE_IMAGES=substr1,substr2
|
||||||
|
extra = [s.strip() for s in os.environ.get("SOC_EXCLUDE_IMAGES", "").split(",") if s.strip()]
|
||||||
seen = []
|
seen = []
|
||||||
for c in conts:
|
for c in conts:
|
||||||
|
cid = c.get("Id", "")
|
||||||
|
if self_id and cid.startswith(self_id):
|
||||||
|
continue # don't scan the collector itself
|
||||||
img = c.get("Image", "")
|
img = c.get("Image", "")
|
||||||
if img and img not in seen:
|
if not img or img in seen or any(x in img for x in extra):
|
||||||
|
continue
|
||||||
seen.append(img)
|
seen.append(img)
|
||||||
return seen
|
return seen
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user