Skip to content

storage: the resource-tag policy rewrite in migrate writes each policy back unconditionally, so an edit made while a server runs can be lost #649

Open

Description

@LeeroyHannigan

extenddb migrate --yes rewrites IAM policies that still use the resource-tag condition keys #421 replaced. For each user, group and role it reads the inline policies, for each user and role the permissions boundary, and then the session policies; it classifies each document and writes the rewritten ones back with a plain put (crates/storage/src/policy_migration.rs:371-407 for inline policies, :410-468 for boundaries and :470-495 for session policies, on main at cf321f0). The write doesn't check that the stored document is still the one it read. A policy edited through the API between the read and the write gets the rewritten copy of its old document, and the edit is lost.

That needs a server serving the catalog while migrate runs. On SQLite it can't happen, because migrate takes the file lock that serve holds (crates/storage-sqlite/src/bootstrapper.rs:494-507). PostgreSQL's migrate holds an advisory lock that serve never takes, and Cassandra and MongoDB take no lock at all, so on those three backends a running server keeps accepting policy edits during the rewrite.

The upgrade manual's procedure stops the server first (docs/manuals/07-upgrade-manual.md:130-134). Only documents that still carry the old keys are written, so once a rewrite has finished cleanly, later runs write nothing. This is read in code; the race wasn't run.

A fix could make each write conditional on the document that was read: an UPDATE ... WHERE on the old value on the SQL backends, a lightweight transaction on Cassandra, and a filter on the old document on MongoDB, with a lost condition counted as a policy to rewrite on the next run. Refusing migrate while a server serves the catalog would also prevent it.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions