Skip to content

PostgreSQL remoteAccess: close the pg_hba.conf opening when a reload fails or the Service is removed #144

Closed

Description

@shipmill-romamo

Found in the review of #141 (PostgreSQL remoteAccess, spec S-006). The nftables rule closes the port in each case below, so nothing is reachable from outside; these are gaps in the second layer.

1. A failed reload during removal leaves the old opening live

engine/ansible/roles/cloudfall_postgresql/tasks/main.yml (the removal path around lines 256 and 277): when remoteAccess is removed, the role deletes the Cloudfall block from pg_hba.conf and reloads. If that reload fails, the run fails, but the file is already without the block, so the next converge sees no change and never reloads. PostgreSQL keeps the old hostssl lines live until a restart.

Expected: a later converge notices that the running rules (pg_hba_file_rules or pg_settings) differ from the file and reloads, or the role reloads whenever the last reload didn't succeed.

2. Removing the whole Service leaves the block and the listener

S-006-10 covers removing remoteAccess from a service. Removing the PostgreSQL Service itself removes the firewall rule but leaves the pg_hba.conf block and listen_addresses = '127.0.0.1,<listenAddress>' on the host.

Expected: whatever the decommission path for a service is, it closes these too, or config validate/converge says what is left behind.

3. Reserved pg_hba words are refused only in the role

#141 makes the role refuse an owned database or owner named all, sameuser, samerole, samegroup or replication (pg_hba reads them as keywords). cloudfall config validate still accepts them, so the refusal comes at converge time. It should be CONFIG_INVALID with a context code at validate time.

Related: #81, #123, docs/specs/006-standalone-postgresql.md.

Activity

  1. shipmill-romamo commented on Oct 27, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: implement parts 1 and 3, for the next release candidate. Part 2 moves to #146, postponed.

    Confirmed on main (2828e49) by reading the code:

    1. engine/ansible/roles/cloudfall_postgresql/tasks/main.yml: the check and the reload run only when: cloudfall_postgresql_hba is changed. A failed reload during removal goes to the rescue, which removes the (already removed) block and fails; the next converge sees an unchanged file and never reloads, so PostgreSQL keeps the old hostssl lines until a restart
    2. Cloudfall has no decommission path for any Service: converge renders only the declared services and nothing records what a host ran before. That is a feature of its own, not a fix to this role, so it is Removing a PostgreSQL Service leaves its pg_hba.conf block and listener on the host #146
    3. The role refuses an owned database or owner named all, sameuser, samerole, samegroup or replication; sdk/src/cloudfall/validation.py doesn't, so the refusal comes only at converge

    The plan:

    • Part 1: make a reload that didn't succeed get retried on the next converge. The rescue leaves a marker file on the host (under the role's own state, not in pg_hba.conf); the next run reloads when the file changed or the marker is there, and removes the marker once pg_reload_conf() returns t. A run with neither stays unchanged, so converge stays idempotent
    • Part 3: config validate refuses those names when the service declares remoteAccess, as CONFIG_INVALID with the context code service_remote_access_name_reserved, pointing at the database's name or owner. The role keeps its own check as the second layer
    • Tests: a role test for the marker path (rescue writes it, the next run reloads and clears it) and validation tests for each reserved word as a name and as an owner; a service without remoteAccess may still use them, as today

    I'll link the PR here.

  2. shipmill-romamo commented on Oct 27, 2026

    @shipmill-romamo
    ContributorAuthor

    @romamo Decided without waiting: cloudfall config validate refuses a PostgreSQL service with remoteAccess whose owned database or owner is named all, sameuser, samerole, samegroup or replication, with the new context code service_remote_access_name_reserved.

    Why: converge already refuses exactly these configs (#141), so no config that works today stops working; the refusal only moves to validate, where every other remoteAccess mistake is caught.
    Not taken: leave the refusal in the role alone, which means the mistake surfaces only after a converge has started on the host.

    Reply with a comment starting with veto before 2026-10-28 11:15 UTC to reverse it, adding what you want instead if you like. A later veto still counts and gets a follow-up.

  3. shipmill-romamo commented on Oct 27, 2026

    @shipmill-romamo
    ContributorAuthor

    The fix is in #147. Part 1: when the pg_hba check or reload fails, the rescue leaves /var/lib/cloudfall/postgresql/<service id>.pg_hba-reload-pending (a new root-only state directory), the next converge checks and reloads even though the file no longer changes, then removes the marker; a run with neither stays changed=0. Part 3: config validate refuses the five pg_hba keywords as an owned database's name or owner on a service with remoteAccess (service_remote_access_name_reserved), and S-006-11 lists the new code. Not verified live: a real pg_reload_conf() failure on a host; the test replays the role's block against a stub psql. Part 2 is #146. This issue closes when #147 merges.

  4. shipmill-romamo commented on Oct 27, 2026

    @shipmill-romamo
    ContributorAuthor

    Released in v0.8.0rc7 (pre-release). uv tool install --prerelease allow cloudfall==0.8.0rc7
    A plain install gets it with the next stable release.
    If you filed this: react 👍 on this comment once it works for you, or reply if it doesn't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdecidedAn agent decided at notify; the maintainer may veto

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions