Skip to content

Commit

Permalink
Fix IntegrityError when giving overlapping team permissions (#401)
Browse files Browse the repository at this point in the history
We hit another version of
#281 from out in the
wild.

The report of this is ansible/awx#15185, and
although it is short on specific of what went on, with some speculation
I was able to mostly logically brute-force out the probable cause. The
imagined reproducer:

- In the "old" AWX UI, go to give a team permission to 2 different roles
to the same thing, like inventory update and adhoc roles.
 - It is assumed that this team has members already.
 - Submit the requests to assign those permissions concurrently.

This fixes that issue by ignoring conflicts on bulk creation of role evaluations.
  • Loading branch information
AlanCoding committed May 24, 2024
1 parent cac0814 commit 0395baa
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 2 deletions.
6 changes: 6 additions & 0 deletions ansible_base/lib/dynamic_config/dynamic_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@
ANSIBLE_BASE_ALLOW_SINGLETON_TEAM_ROLES = False
ANSIBLE_BASE_ALLOW_SINGLETON_ROLES_API = True

# Pass ignore_conflicts=True for bulk_create calls for role evaluations
# this should be fine to resolve cross-process conflicts as long as
# directionality is the same - adding or removing permissions
# A value of False would result in more errors but be more conservative
ANSIBLE_BASE_EVALUATIONS_IGNORE_CONFLICTS = True

# User flags that can grant permission before consulting roles
ANSIBLE_BASE_BYPASS_SUPERUSER_FLAGS = ['is_superuser']
ANSIBLE_BASE_BYPASS_ACTION_FLAGS = {}
Expand Down
6 changes: 4 additions & 2 deletions ansible_base/rbac/caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Optional
from uuid import UUID

from django.conf import settings

from ansible_base.rbac.models import ObjectRole, RoleDefinition, RoleEvaluation, RoleEvaluationUUID
from ansible_base.rbac.permission_registry import permission_registry
from ansible_base.rbac.prefetch import TypesPrefetch
Expand Down Expand Up @@ -193,9 +195,9 @@ def compute_object_role_permissions(object_roles=None, types_prefetch=None):
else:
raise RuntimeError(f'Could not find a place in cache for {evaluation}')
if to_add_int:
RoleEvaluation.objects.bulk_create(to_add_int)
RoleEvaluation.objects.bulk_create(to_add_int, ignore_conflicts=settings.ANSIBLE_BASE_EVALUATIONS_IGNORE_CONFLICTS)
if to_add_uuid:
RoleEvaluationUUID.objects.bulk_create(to_add_uuid)
RoleEvaluationUUID.objects.bulk_create(to_add_uuid, ignore_conflicts=settings.ANSIBLE_BASE_EVALUATIONS_IGNORE_CONFLICTS)

if to_delete:
logger.info(f'Deleting {len(to_delete)} object-permission records')
Expand Down

0 comments on commit 0395baa

Please sign in to comment.