Skip to content

feat: backfill RBAC role assignments for gap-window domains - #1445

Merged
dkliban merged 1 commit into
pulp:mainfrom
CryptoRodeo:feat/pulp-2319
Sep 3, 2026
Merged

feat: backfill RBAC role assignments for gap-window domains#1445
dkliban merged 1 commit into
pulp:mainfrom
CryptoRodeo:feat/pulp-2319

Conversation

@CryptoRodeo

@CryptoRodeo CryptoRodeo commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Add migration 0021 to backfill RBAC role assignments (PULP-1893). Some domains were created between the 0019 migration and the PULP-2119 dual-write deploy but never got their UserRole/GroupRole assignments. This fills them in.

It re-runs 0019's convert_domainorgs_to_roles over every DomainOrg row. (0019's module name starts with a digit, so we load the function via importlib instead of a normal import.) The function is idempotent, so domains that already have roles are skipped and only the missing ones get filled.

Reverse is a no-op: a backfill can't tell which rows it created, and this keeps rollback separate from the later PULP-2120 permission switch.

Shipped on its own, apart from PULP-2120, so the backfill can be tested alone and a bad one rolls back without touching the risky permission change.

Summary by Sourcery

Backfill RBAC assignments for domains missed between the original conversion migration and dual-write deployment while preserving existing role permissions and keeping rollback non-destructive.

Bug Fixes:

  • Backfill missing RBAC role assignments for DomainOrg records created during the migration gap window.

Enhancements:

  • Make the existing domain-to-role conversion reusable for scoped, idempotent backfills without altering current service-role permissions or readonly policy assignments.

@sourcery-ai

sourcery-ai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Introduces migration 0021 to backfill missing DomainOrg UserRole and GroupRole assignments by reusing the idempotent 0019 conversion, while disabling permission replacement to preserve current service-role permissions. The migration is independently deployable and intentionally irreversible via a no-op reverse.

Sequence diagram for the DomainOrg RBAC backfill migration

sequenceDiagram
    participant Migration0021
    participant Migration0019
    participant DomainOrg
    participant Role
    participant UserRole
    participant GroupRole
    participant ServiceRolePermissions

    Migration0021->>Migration0019: convert_domainorgs_to_roles(apps, schema_editor, set_permissions=False)
    Migration0019->>Role: _ensure_service_roles(apps, set_permissions=False)
    Role-->>Migration0019: get_or_create service roles
    Migration0019->>DomainOrg: read every DomainOrg row
    loop each DomainOrg
        Migration0019->>UserRole: get_or_create missing assignments
        Migration0019->>GroupRole: get_or_create missing assignments
    end
    Migration0019-->>Migration0021: backfill complete
    Migration0021-->>ServiceRolePermissions: permissions.set not called
    Migration0021-->>Migration0021: reverse is noop
Loading

File-Level Changes

Change Details Files
Add an idempotent migration to restore missing DomainOrg RBAC assignments.
  • Load the existing 0019 conversion function dynamically and rerun it for all DomainOrg records.
  • Use the existing get-or-create assignment logic so already converted domains are unchanged.
  • Make the migration reverse as a no-op because created assignments cannot be distinguished safely.
pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py
CHANGES/2319.bugfix
Make the reusable conversion preserve service-role permission changes during backfills.
  • Add a set_permissions option to the service-role creation and DomainOrg conversion helpers.
  • Disable permission replacement for the 0021 backfill while retaining permission initialization for the original 0019 migration.
  • Continue returning or creating the service roles needed for DomainOrg assignment.
pulp_service/pulp_service/app/migrations/0019_convert_domainorg_to_roles.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py" line_range="25" />
<code_context>
+
+    operations = [
+        migrations.RunPython(
+            _migration_0019.convert_domainorgs_to_roles,
+            migrations.RunPython.noop,
+        ),
</code_context>
<issue_to_address>
**issue (broader_impact):** The backfill invokes 0019's entire conversion function, which calls `_ensure_service_roles` and executes `permissions.set(...)` for `service.domain_admin` and `service.domain_viewer`. This replaces the existing permission memberships, so a deployment can overwrite intentional role customizations or permission changes made since migration 0019; the operation is not limited to filling missing DomainOrg assignments as the surrounding comments claim.

**Triggers:** When the service roles have permission memberships that differ from the current set of plugin permissions.

**Suggested fix:** Extract or invoke only the DomainOrg role-assignment portion of the conversion, leaving service-role permission memberships and other one-time policy assignments untouched.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and the migration persists RBAC role assignments, so an incorrect conversion could grant or remove access for affected domains and require manual database cleanup. Its reverse operation is a no-op, meaning reverting the code would not remove assignments already created.

Blocking findings: pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py:25


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py Outdated
@CryptoRodeo

Copy link
Copy Markdown
Contributor Author

@sourcery-ai review

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py" line_range="24" />
<code_context>
+    # membership, so running it here would overwrite any service-role permission
+    # changes made since 0019. The post_migrate handler keeps those permissions
+    # authoritative; this backfill leaves them untouched.
+    _migration_0019.convert_domainorgs_to_roles(apps, schema_editor, set_permissions=False)
+
+
</code_context>
<issue_to_address>
**issue (broader_impact):** The backfill invokes the entire 0019 conversion, which also processes the current `DOMAIN_ACCESS_POLICIES` and creates readonly-group role assignments independently of `DomainOrg` rows. A policy added or changed after 0019 therefore grants new readonly roles to unrelated existing domains during 0021, despite the migration's stated scope being only missing DomainOrg assignments.

**Triggers:** When `DOMAIN_ACCESS_POLICIES` differs from the configuration used when migration 0019 ran.

**Suggested fix:** Extract or add a conversion helper that processes only DomainOrg assignments, and do not execute 0019's readonly-policy loop from the backfill.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and this migration persists RBAC role assignments for existing domains, which can grant or withhold authorization. If the assignment logic is wrong, reverting the code does not remove those persisted access changes; they would require a separate corrective migration or manual cleanup.

Blocking findings: pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py:24


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread pulp_service/pulp_service/app/migrations/0021_backfill_domainorg_roles.py Outdated
Add data migration 0021 that re-runs migration 0019's
DomainOrg-to-roles conversion (PULP-1893) over every DomainOrg row.
This backfills the finite, now-frozen set of domains created in the
window between the initial 0019 migration and the PULP-2119 dual-write
deploy -- rows that have domains but no UserRole/GroupRole assignments.

The migration imports convert_domainorgs_to_roles from 0019 via
importlib (the module name starts with a digit, so a normal import will
not parse) and runs it with set_permissions=False. The conversion is
idempotent (get_or_create throughout), so domains that already have
their roles -- from 0019 or the 2119 dual-write -- are skipped and only
gap domains are filled. set_permissions=False keeps the backfill limited
to DomainOrg role assignments: it does not call permissions.set(...) on
the service roles, so it cannot overwrite service-role permission
membership changes made since 0019 (the post_migrate handler keeps those
authoritative). Reverse is a no-op: a backfill cannot distinguish rows
it created from pre-existing ones, and this keeps rollback isolated from
the later PULP-2120 permission-class switch.

Shipped as its own deploy, separate from PULP-2120, so the backfill can
be validated independently and a bad backfill rolls back without
reverting the high-risk permission switch-over.

Signed-off-by: Bryan Ramos <bramos@redhat.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dkliban
dkliban merged commit ad17241 into pulp:main Sep 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants