diff --git a/.github/workflows/private-names.yml b/.github/workflows/private-names.yml new file mode 100644 index 0000000..aa7345b --- /dev/null +++ b/.github/workflows/private-names.yml @@ -0,0 +1,17 @@ +name: Private names + +on: + pull_request: + push: + branches: [main] + +jobs: + check: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - name: The check catches what it should + run: python3 scripts/check-private-names.py --self-test + - name: No private machine, person, or agent names + run: python3 scripts/check-private-names.py diff --git a/scripts/check-private-names.py b/scripts/check-private-names.py new file mode 100755 index 0000000..f1bc39f --- /dev/null +++ b/scripts/check-private-names.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +"""Keep private machine, person, and agent names out of this public repository. + +Fails when a tracked file names one of the fleet's machines, a home directory +under /home or /Users, a person/ ID, or an internal agent or mission ID +(agent/fleet/, mission/fleet/, mission-run/fleet/). Write invented +examples instead: web1.example.com, /home/example, /Users/example, +person/alex, agent/example/worker. + +Machine names are listed as SHA-256 digests of the lowercase name, so this +file does not publish the names it keeps out. To add a machine, append the +output of `printf %s NAME | shasum -a 256`. + +A line that must stay as it is goes in .private-names-allow: one regular +expression per line, searched in `path:text of the line`. Blank lines and +lines starting with # are ignored. + +Run it from anywhere inside the repository: python3 scripts/check-private-names.py +With --self-test it checks its own patterns instead of the repository. +""" + +import hashlib +import re +import subprocess +import sys +from pathlib import Path + +MACHINE_DIGESTS = { + "a994ffcab684f9e2136b0681c20d2a5ef5f23a5cb7b64ab8934d15a888cc4ea3", + "2c619e6895b513481a07dae6c4b5781282ef1eee7a7f16744fafe7dbbd3e5ca2", + "46b6312339466d3b206325f6f402e1fae56cd65f117c779e3b9259833ffbcdf0", + "9fe430e5274621be518924ed90d2355f39eeb1d4d98fb00ea0022f3a26ba5595", + "5881d66b8738b483578c8479c59f09856a5447b47bbd2660cff7dc92e1607a2d", + "294aa8d75483b8331e3ba6a7f24aea15202747f36de65197e7bc6194880b2558", + "151ec47d45b057450da03010df462bf604183571812f9ba66598b9fb8f8b692c", +} + +ALLOW_FILE = ".private-names-allow" + +WORD = re.compile(r"[a-z0-9]+(?:-[a-z0-9]+)*") +HOME = re.compile(r"/(?:home|Users)/([A-Za-z0-9._-]+)") +PERSON = re.compile(r"(?