mirror of
https://github.com/ansible/awx.git
synced 2026-02-26 15:36:04 -03:30
prevent tower group delete and update
* related to https://github.com/ansible/ansible-tower/issues/7931 * The Tower Instance group is special. It should always exist, so prevent any delete to it. * Only allow super users to associate/disassociate instances the 'tower' instance group. * Do not allow fields of tower instance group to be changed.
This commit is contained in:
@@ -17,7 +17,7 @@ logger = logging.getLogger('awx.api.permissions')
|
|||||||
|
|
||||||
__all__ = ['ModelAccessPermission', 'JobTemplateCallbackPermission',
|
__all__ = ['ModelAccessPermission', 'JobTemplateCallbackPermission',
|
||||||
'TaskPermission', 'ProjectUpdatePermission', 'InventoryInventorySourcesUpdatePermission',
|
'TaskPermission', 'ProjectUpdatePermission', 'InventoryInventorySourcesUpdatePermission',
|
||||||
'UserPermission', 'IsSuperUser']
|
'UserPermission', 'IsSuperUser', 'InstanceGroupTowerPermission',]
|
||||||
|
|
||||||
|
|
||||||
class ModelAccessPermission(permissions.BasePermission):
|
class ModelAccessPermission(permissions.BasePermission):
|
||||||
@@ -227,3 +227,12 @@ class IsSuperUser(permissions.BasePermission):
|
|||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
return request.user and request.user.is_superuser
|
return request.user and request.user.is_superuser
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceGroupTowerPermission(ModelAccessPermission):
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
if request.method not in permissions.SAFE_METHODS:
|
||||||
|
if obj.name == "tower":
|
||||||
|
return False
|
||||||
|
return super(InstanceGroupTowerPermission, self).has_object_permission(request, view, obj)
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,14 @@ from awx.main.utils import (
|
|||||||
from awx.main.utils.encryption import encrypt_value
|
from awx.main.utils.encryption import encrypt_value
|
||||||
from awx.main.utils.filters import SmartFilter
|
from awx.main.utils.filters import SmartFilter
|
||||||
from awx.main.utils.insights import filter_insights_api_response
|
from awx.main.utils.insights import filter_insights_api_response
|
||||||
|
from awx.api.permissions import (
|
||||||
from awx.api.permissions import * # noqa
|
JobTemplateCallbackPermission,
|
||||||
|
TaskPermission,
|
||||||
|
ProjectUpdatePermission,
|
||||||
|
InventoryInventorySourcesUpdatePermission,
|
||||||
|
UserPermission,
|
||||||
|
InstanceGroupTowerPermission,
|
||||||
|
)
|
||||||
from awx.api.renderers import * # noqa
|
from awx.api.renderers import * # noqa
|
||||||
from awx.api.serializers import * # noqa
|
from awx.api.serializers import * # noqa
|
||||||
from awx.api.metadata import RoleMetadata, JobTypeMetadata
|
from awx.api.metadata import RoleMetadata, JobTypeMetadata
|
||||||
@@ -651,6 +657,7 @@ class InstanceGroupDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAP
|
|||||||
view_name = _("Instance Group Detail")
|
view_name = _("Instance Group Detail")
|
||||||
model = InstanceGroup
|
model = InstanceGroup
|
||||||
serializer_class = InstanceGroupSerializer
|
serializer_class = InstanceGroupSerializer
|
||||||
|
permission_classes = (InstanceGroupTowerPermission,)
|
||||||
|
|
||||||
|
|
||||||
class InstanceGroupUnifiedJobsList(SubListAPIView):
|
class InstanceGroupUnifiedJobsList(SubListAPIView):
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ def instance_group(job_factory):
|
|||||||
return ig
|
return ig
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def tower_instance_group():
|
||||||
|
ig = InstanceGroup(name='tower')
|
||||||
|
ig.save()
|
||||||
|
return ig
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def create_job_factory(job_factory, instance_group):
|
def create_job_factory(job_factory, instance_group):
|
||||||
def fn(status='running'):
|
def fn(status='running'):
|
||||||
@@ -71,3 +78,13 @@ def test_delete_instance_group_jobs_running(delete, instance_group_jobs_running,
|
|||||||
assert response.data['error'] == u"Resource is being used by running jobs."
|
assert response.data['error'] == u"Resource is being used by running jobs."
|
||||||
assert response_sorted == expect_sorted
|
assert response_sorted == expect_sorted
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_delete_tower_instance_group_prevented(delete, options, tower_instance_group, admin):
|
||||||
|
url = reverse("api:instance_group_detail", kwargs={'pk': tower_instance_group.pk})
|
||||||
|
delete(url, None, admin, expect=403)
|
||||||
|
resp = options(url, None, admin, expect=200)
|
||||||
|
actions = ['DELETE', 'PATCH', 'PUT']
|
||||||
|
for action in actions:
|
||||||
|
assert action not in resp.data['actions']
|
||||||
|
assert 'GET' in resp.data['actions']
|
||||||
|
|||||||
Reference in New Issue
Block a user