bitenforcer
bitenforcer legge una policy di hardening dichiarativa e risponde in modo completo a una sola domanda:
"Se applicassi questa policy a questa macchina, cosa cambierebbe esattamente — e cosa potrebbe succedere al mio accesso?"
| Release | 0.1.0-ga, commit 4c6ce93, compilato con go1.25.12 |
| Piattaforme | Solo Linux amd64/arm64 — macOS e Windows non sono pubblicati, ed ecco perché |
| Supply chain | Build riproducibile, SBOM CycloneDX, firma cosign, attestazione dell'SBOM, SHA256SUMS firmato |
| Forma | Strumento da riga di comando a esecuzione singola. Nessun demone, nessuna telemetria, nessun heartbeat |
bitenforcer v1 fornisce validate e apply --dry-run. Pianifica ogni modifica,
convalida il contenuto che scriverebbe, esegue le sue guardie anti-lockout — e poi si ferma.
Non scrive sull'host, e nessun flag glielo fa fare.
Questa è una decisione deliberata sull'ambito, non un bug, un'interruzione di servizio o un'impostazione che ti sfugge. Il perché vale dieci minuti del tuo tempo prima di pianificare un rollout.
Le guardie stesse, e il resoconto completo del perché l'enforcement è fuori dall'ambito, sono su Le guardie, e perché la v1 non applica nulla.
Cosa fa
Puntalo su una policy YAML:
bitenforcer validate --config policy.yaml # is the policy well-formed?
bitenforcer apply --config policy.yaml --dry-run # what would it do to THIS host?
Il pre-flight nomina ogni file che scriverebbe e i byte che scriverebbe, ogni unità systemd che abiliterebbe, disabiliterebbe, maschererebbe o in cui inserirebbe un frammento di hardening, ogni regola di firewall, ogni sysctl, ogni account e permesso — nell'ordine in cui verrebbero applicati.
Dove esiste un validatore reale, il contenuto candidato viene passato attraverso di esso:
| Artefatto | Validatore |
|---|---|
sshd_config | sshd -t -f <candidate> |
| sudoers | visudo -c |
| ruleset nftables | nft -c -f <candidate> |
| ruleset iptables | iptables-restore --test |
Così "questa policy genera un sshd_config che sshd rifiuterà" viene rilevato prima che qualcuno ne risponda — e non alle 03:00, quando il demone non riesce a riavviarsi.
Insieme a questo, le guardie anti-lockout riportano cosa farebbe la tua policy al tuo stesso accesso, misurato rispetto alla sessione in cui stai effettivamente lavorando.
Ciò che non farà è tirare a indovinare. Un modulo i cui prerequisiti mancano genera un
errore anziché fare assunzioni. Una sessione che non può essere misurata viene riportata come
non misurata, mai come "nessuno è a rischio". Un validatore che non può essere eseguito
dichiara NOT VALIDATED per ciascun file, con la ragione, anziché lasciar intendere che il
contenuto sia stato verificato.
Output reale del pre-flight
Questa è un'esecuzione reale del binario 0.1.0-ga distribuito, contro il template standard,
su un normale host Ubuntu, come utente non root. Solo l'indirizzo IP dell'operatore è stato
sostituito con un indirizzo di documentazione, e un blocco di errore nft molto lungo è stato
accorciato.
$ bitenforcer generate --template standard --output-file policy.yaml
Example configuration written to policy.yaml
$ bitenforcer validate --config policy.yaml
Configuration 'standard-hardening' is valid.
Environment : staging
Compliance : [CIS-L1]
A valid policy is not a safe one: run `bitenforcer apply --dry-run` to see what it
would change and which guards fire.
(FR) Politique valide. Une politique valide n'est pas pour autant sûre : utilisez
`apply --dry-run`.
$ bitenforcer apply --config policy.yaml --dry-run
=== PRE-FLIGHT: every change this run would make ===
operator "ubuntu" is on an SSH session whose peer socket was NOT measured
(SSH_CONNECTION/SSH_CLIENT in this process's environment (an inherited, settable
environment variable -- a hint, NOT a measured socket)); any address in the
environment is a hint, not evidence
NOT EXAMINED on this host (the rest of the pre-flight below is unaffected):
selinux: SELinux prerequisites check failed: SELinux tools not found
(getenforce not in PATH)
These modules were SKIPPED, not found compliant — this run says nothing
about whether the host matches that part of the policy.
(FR) Modules NON EXAMINÉS sur cet hôte : ignorés, et non déclarés conformes.
1. [command] users /etc/passwd
chmod 0644 /etc/passwd
2. [command] users /etc/passwd
chown root:root /etc/passwd
3. [command] users /etc/shadow
chmod 0640 /etc/shadow
4. [command] users /etc/shadow
chown root:root /etc/shadow
5. [command] users /etc/group
chmod 0644 /etc/group
6. [command] users /etc/group
chown root:root /etc/group
7. [command] users /etc/gshadow
chmod 0640 /etc/gshadow
8. [command] users /etc/gshadow
chown root:root /etc/gshadow
9. [file-write] ssh /etc/ssh/sshd_config
1194 bytes, mode 0600, validated with sshd -t -f <candidate>; NOT VALIDATED in
this dry run (the validator could not be run in this context: sshd -t needs root
to read the host keys (sshd: no hostkeys available -- exiting.)) — re-run the
dry run as root to validate
10. [file-write] firewall /etc/nftables.conf
566 bytes, mode 0600, validated with nft -c -f <candidate>; NOT VALIDATED in
this dry run (nft -c needs root […]) — re-run the dry run as root to validate
11. [file-write] kernel /etc/sysctl.d/99-bitenforcer.conf
672 bytes, mode 0644, validated with sysctl key syntax check
12. [command] kernel /etc/sysctl.d/99-bitenforcer.conf
sysctl -p /etc/sysctl.d/99-bitenforcer.conf
=== PRE-FLIGHT ADVISORIES (the guards; they did NOT block this run) ===
These are the lockout guards. They are advisory: they report the shapes they
recognise, and seven independent reviewers each found one they did not — which is
why this release does not apply anything. Treat a finding as a reason to change the
policy, never as the full list of ways it could strand you. Re-run with
--guards=blocking to have findings exit non-zero, e.g. to gate a policy in CI.
1. [kernel-remote-access-loss] this run would set net.ipv4.conf.all.rp_filter=1,
which drops any packet whose reply route does not leave by the interface it
arrived on
evidence: bitenforcer measures the interface carrying your session (eth0)
but not this host's routing table, so it cannot show that the route back
to 198.51.100.24 leaves by that same interface. On a host with two
uplinks, a VPN, or asymmetric routing, strict reverse-path filtering
drops your session and every future connection from that address
remedy: run `ip route get 198.51.100.24` and confirm it leaves by eth0;
if it does, say so for this one parameter, and keep a second session
open while you apply
override: re-run with --acknowledge kernel-remote-access-loss (this guard only)
2. [kernel-remote-access-loss] this run would set net.ipv4.ip_forward=0, and
bitenforcer cannot establish whether this host routes the network your session
arrives through
…
DRY RUN: nothing above was applied and this host was not changed.
This is the only mode bitenforcer v1 runs in; enforcement is not part of this release.
(FR) SIMULATION : rien n'a été appliqué et cet hôte n'a pas été modifié.
Tre cose in quell'output sono l'intero prodotto:
NOT EXAMINEDè una risposta, non un'omissione. Gli strumenti SELinux sono assenti su Ubuntu standard, quindi il modulo selinux viene riportato come saltato, esplicitamente non dichiarato conforme, e il resto del pre-flight prosegue. Un'esecuzione che non dice nulla su un controllo è molto diversa da un'esecuzione che dice che il controllo è a posto.NOT VALIDATEDnomina il perché, file per file.sshd -tha bisogno di root per leggere le chiavi host, quindi come utente normale lo strumento ti dice che il contenuto non è stato verificato e cosa fare al riguardo — invece di lasciar intendere in silenzio che lo sia stato.- Il rilievo della guardia porta con sé evidenze, un rimedio e un override per singola guardia. Non dice "rischioso". Dice quale parametro, cosa ha misurato, cosa non è riuscito a misurare, e l'esatto comando da eseguire per risolvere la questione.
Cosa vale per te oggi
È facile leggere "non applica modifiche" come "non fa nulla". Ecco cosa ti dà davvero uno strumento di solo pre-flight:
- Un artefatto per la finestra di manutenzione. Allega l'output del pre-flight alla richiesta di modifica. Ogni file, unità, regola e sysctl, in ordine, con i byte.
- Un gate in CI.
--guards=blockingfa fallire la pipeline quando una baseline reciderebbe l'accesso, prima che arrivi su un host. - Rilevare presto contenuti di policy errati.
sshd -tenft -cgirano sul contenuto candidato, così una policy che genera una configurazione non interpretabile viene intercettata in revisione. - Drift su cui puoi agire, in sicurezza. Esegui il dry run su una flotta e leggi cosa ciascun host riporta che servirebbe — senza alcuna possibilità di cambiare qualcosa per sbaglio.
- Una mappa di copertura onesta.
NOT EXAMINEDti dice dove lo strumento non ha nulla da dire, così non scambi il silenzio per conformità.
Policy as code
bitenforcer generate --template standard --output-file policy.yaml
Template: minimal, standard, strict. Sono punti di partenza fissi da modificare — non
leggono l'host e non derivano una postura dalla macchina su cui li hai eseguiti. Le policy
generate fanno round-trip: reimmetti l'output in validate e passa.
validate va oltre il controllo dello schema: una policy che imposta una chiave che nulla
implementa viene rifiutata al caricamento, per nome, con la dichiarazione di ciò che non
accade. Un'impostazione che viene interpretata ma è inerte è il difetto che questi prodotti
hanno passato un mese a rimuovere da sé stessi.
validate legge il file di policy e nient'altro — non guarda questo host. Esegui
bitenforcer apply --config <file> --dry-run per scoprire cosa cambierebbe qui.
Piattaforme
0.1.0-ga pubblica due binari firmati, e il vuoto è deliberato:
| Piattaforma | Pubblicata | Perché |
|---|---|---|
Linux amd64 | Sì | |
Linux arm64 | Sì | |
macOS amd64/arm64 | No | Trattenuta — vedi sotto |
Windows amd64 | No | Trattenuta — vedi sotto |
bitenforcer è solo per Linux perché tutto il suo oggetto è Linux. Ogni modulo che pianifica
riguarda un meccanismo Linux: ruleset iptables/nftables, chiavi sysctl sotto /proc/sys,
unit systemd, SELinux e AppArmor, e /etc/passwd, /etc/shadow, /etc/gshadow e sudoers con
i loro permessi e proprietari POSIX. Lo stesso vale per i validatori attraverso cui fa passare
il contenuto candidato — sshd -t, visudo -c, nft -c, iptables-restore --test.
Una build per macOS o Windows compilerebbe. È esattamente questo il problema: partirebbe,
accetterebbe una policy e produrrebbe un pre-flight in cui ogni modulo risulterebbe
NOT EXAMINED — un rapporto che sembra un'esecuzione riuscita e non dice nulla sull'host.
Dato che questo strumento esiste per dirti che cosa farebbe un cambiamento prima che tu lo
faccia, un binario la cui uscita onesta è «non ho nulla da dire su questa macchina» è peggio di
nessun binario. Non viene pubblicato, così nessuno lo scambia per copertura.
Se ti serve la postura di hardening di un host macOS, quello è il collector posture di
bitcollector, distribuito su macOS, che riporta controllo per
controllo se è stato osservato, non osservato, o non supportato dall'agente lì.
Passi successivi
- Le guardie, e perché la v1 non applica nulla — le diciotto guardie anti-lockout, il gate in CI e perché il percorso di enforcement è deliberatamente fuori da questa release.
- Verificare i tuoi download — fallo prima della prima esecuzione.
- bitcollector — la metà della coppia che riporta, e da dove arrivano le evidenze continue sulla postura.
- Framework di conformità — come si mappano i controlli.
Questa pagina ti è stata utile?