Repository navigation
Audit remoteAccess firewall rules and listener without false drift (#143) - #148
Merged
Merged
Conversation
) firewall.allowedInbound now expects one 'tcp/<port> from <cidr>' entry per declared remoteAccess source and parses the ip/ip6 saddr match of each accepted nftables rule, normalising nft's bare /32 and /128 addresses. services.bind accepts a listener on the declared listenAddress. The source-restricted rules come from one SDK function, remote_access_rules_for_server, which the engine inventory now uses too. Servers without remoteAccess audit exactly as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A service that declares remoteAccess now matches services.bind only when both its bind address and its listenAddress have a listener on the port, so a PostgreSQL that failed to bind listenAddress is reported as drift. Services without remoteAccess keep today's check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cloudfall auditreported false drift on a server whose PostgreSQL service declaresspec.postgresql.remoteAccess:firewall.allowedInboundnow expects onetcp/<port> from <cidr>entry per declared source, next to today'stcp/22-style entries. The observed side reads theip saddr/ip6 saddrmatch of each accepted rule innft -joutput: a bare address (nft's form for a /32 or /128) and{"prefix": {"addr", "len"}}are normalised to canonical CIDR, so10.1.0.7/32matches nft's10.1.0.7. Any other saddr shape (set, negation, range) is kept as its raw JSON, so it never matches and shows as driftservices.bind[<id>]for a service withremoteAccessmatches only when both the bind address andremoteAccess.listenAddresshave a listener on the port and no other non-loopback listener exists: a PostgreSQL that failed to bindlistenAddressis drift. For such a service the desired object reportsloopbackOnly: falseand addsremoteAccess: {listenAddress}; services withoutremoteAccesskeep the same keys and valuescloudfall.inventory.remote_access_rules_for_server(returningSourceRestrictedFirewallRule), which replaces the engine's private_remote_access_rules. The engine's refusals (no firewall on the server; a source of every address) keep their order and messagesServers without
remoteAccessaudit exactly as before.Tests
sdk/tests/test_audit.py: a snapshot with the rendered remoteAccess rules (IPv4 prefix, a bare /32, anip6 saddrprefix) and the10.0.0.2:5432listener audits compliant (fails on main); the port open to every address, a wrong source (fails on main's output form), a listener on an undeclared or wildcard address (next to the declared one), and a remoteAccess service listening only on 127.0.0.1 are drift; a server without remoteAccess yields the samefirewall.allowedInboundandservices.bindvalues as beforeuv run ruff check .,uv run mypy, anduv run pytest sdk/tests/test_audit.py sdk/tests/test_owned_postgresql.py engine/tests/test_postgresql_remote_access.py engine/tests/test_ansible_inventory.py engine/tests/test_firewall_templates.py(85 passed)Fixes #143
🤖 Generated with Claude Code