Passa al contenuto principale
Versione: 1.0.0

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?"

Release0.1.0-ga, commit 4c6ce93, compilato con go1.25.12
PiattaformeSolo Linux amd64/arm64 — macOS e Windows non sono pubblicati, ed ecco perché
Supply chainBuild riproducibile, SBOM CycloneDX, firma cosign, attestazione dell'SBOM, SHA256SUMS firmato
FormaStrumento da riga di comando a esecuzione singola. Nessun demone, nessuna telemetria, nessun heartbeat
La v1 non modifica gli host

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:

ArtefattoValidatore
sshd_configsshd -t -f <candidate>
sudoersvisudo -c
ruleset nftablesnft -c -f <candidate>
ruleset iptablesiptables-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:

  1. 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.
  2. NOT VALIDATED nomina il perché, file per file. sshd -t ha 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.
  3. 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=blocking fa fallire la pipeline quando una baseline reciderebbe l'accesso, prima che arrivi su un host.
  • Rilevare presto contenuti di policy errati. sshd -t e nft -c girano 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 EXAMINED ti 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.

Una policy valida non è una policy sicura

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:

PiattaformaPubblicataPerché
Linux amd64Sì
Linux arm64Sì
macOS amd64/arm64NoTrattenuta — vedi sotto
Windows amd64NoTrattenuta — 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​

Questa pagina ti è stata utile?