mirror of
https://github.com/ansible/awx.git
synced 2026-03-24 04:15:02 -02:30
Adding credential and execution environment roles validates that the user belongs to the same org as the credential or EE. In some situations, the user-org membership has not yet been synced from gateway to controller. In this case, controller will make a request to gateway to check if the user is part of the org. Signed-off-by: Seth Foster <fosterbseth@gmail.com>
This commit is contained in:
@@ -49,6 +49,11 @@ from awx.main.models import Team, Organization
|
|||||||
from awx.main.utils import encrypt_field
|
from awx.main.utils import encrypt_field
|
||||||
from . import injectors as builtin_injectors
|
from . import injectors as builtin_injectors
|
||||||
|
|
||||||
|
# DAB
|
||||||
|
from ansible_base.resource_registry.tasks.sync import get_resource_server_client
|
||||||
|
from ansible_base.resource_registry.utils.settings import resource_server_defined
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['Credential', 'CredentialType', 'CredentialInputSource', 'build_safe_env']
|
__all__ = ['Credential', 'CredentialType', 'CredentialInputSource', 'build_safe_env']
|
||||||
|
|
||||||
logger = logging.getLogger('awx.main.models.credential')
|
logger = logging.getLogger('awx.main.models.credential')
|
||||||
@@ -77,6 +82,46 @@ def build_safe_env(env):
|
|||||||
return safe_env
|
return safe_env
|
||||||
|
|
||||||
|
|
||||||
|
def check_resource_server_for_user_in_organization(user, organization, requesting_user):
|
||||||
|
if not resource_server_defined():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not requesting_user:
|
||||||
|
return False
|
||||||
|
|
||||||
|
client = get_resource_server_client(settings.RESOURCE_SERVICE_PATH, jwt_user_id=str(requesting_user.resource.ansible_id), raise_if_bad_request=False)
|
||||||
|
# need to get the organization object_id in resource server, by querying with ansible_id
|
||||||
|
response = client._make_request(path=f'resources/?ansible_id={str(organization.resource.ansible_id)}', method='GET')
|
||||||
|
response_json = response.json()
|
||||||
|
if response.status_code != 200:
|
||||||
|
logger.error(f'Failed to get organization object_id in resource server: {response_json.get("detail", "")}')
|
||||||
|
return False
|
||||||
|
|
||||||
|
if response_json.get('count', 0) == 0:
|
||||||
|
return False
|
||||||
|
org_id_in_resource_server = response_json['results'][0]['object_id']
|
||||||
|
|
||||||
|
client.base_url = client.base_url.replace('/api/gateway/v1/service-index/', '/api/gateway/v1/')
|
||||||
|
# find role assignments with:
|
||||||
|
# - roles Organization Member or Organization Admin
|
||||||
|
# - user ansible id
|
||||||
|
# - organization object id
|
||||||
|
|
||||||
|
response = client._make_request(
|
||||||
|
path=f'role_user_assignments/?role_definition__name__in=Organization Member,Organization Admin&user__resource__ansible_id={str(user.resource.ansible_id)}&object_id={org_id_in_resource_server}',
|
||||||
|
method='GET',
|
||||||
|
)
|
||||||
|
response_json = response.json()
|
||||||
|
if response.status_code != 200:
|
||||||
|
logger.error(f'Failed to get role user assignments in resource server: {response_json.get("detail", "")}')
|
||||||
|
return False
|
||||||
|
|
||||||
|
if response_json.get('count', 0) > 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
|
class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
|
||||||
"""
|
"""
|
||||||
A credential contains information about how to talk to a remote resource
|
A credential contains information about how to talk to a remote resource
|
||||||
@@ -320,10 +365,16 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
|
|||||||
else:
|
else:
|
||||||
raise ValueError('{} is not a dynamic input field'.format(field_name))
|
raise ValueError('{} is not a dynamic input field'.format(field_name))
|
||||||
|
|
||||||
def validate_role_assignment(self, actor, role_definition):
|
def validate_role_assignment(self, actor, role_definition, **kwargs):
|
||||||
if self.organization:
|
if self.organization:
|
||||||
if isinstance(actor, User):
|
if isinstance(actor, User):
|
||||||
if actor.is_superuser or Organization.access_qs(actor, 'member').filter(id=self.organization.id).exists():
|
if actor.is_superuser:
|
||||||
|
return
|
||||||
|
if Organization.access_qs(actor, 'member').filter(id=self.organization.id).exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
requesting_user = kwargs.get('requesting_user', None)
|
||||||
|
if check_resource_server_for_user_in_organization(actor, self.organization, requesting_user):
|
||||||
return
|
return
|
||||||
if isinstance(actor, Team):
|
if isinstance(actor, Team):
|
||||||
if actor.organization == self.organization:
|
if actor.organization == self.organization:
|
||||||
|
|||||||
@@ -58,11 +58,20 @@ class ExecutionEnvironment(CommonModel):
|
|||||||
def get_absolute_url(self, request=None):
|
def get_absolute_url(self, request=None):
|
||||||
return reverse('api:execution_environment_detail', kwargs={'pk': self.pk}, request=request)
|
return reverse('api:execution_environment_detail', kwargs={'pk': self.pk}, request=request)
|
||||||
|
|
||||||
def validate_role_assignment(self, actor, role_definition):
|
def validate_role_assignment(self, actor, role_definition, **kwargs):
|
||||||
|
from awx.main.models.credential import check_resource_server_for_user_in_organization
|
||||||
|
|
||||||
if self.managed:
|
if self.managed:
|
||||||
raise ValidationError({'object_id': _('Can not assign object roles to managed Execution Environments')})
|
raise ValidationError({'object_id': _('Can not assign object roles to managed Execution Environments')})
|
||||||
if self.organization_id is None:
|
if self.organization_id is None:
|
||||||
raise ValidationError({'object_id': _('Can not assign object roles to global Execution Environments')})
|
raise ValidationError({'object_id': _('Can not assign object roles to global Execution Environments')})
|
||||||
|
|
||||||
if actor._meta.model_name == 'user' and (not actor.has_obj_perm(self.organization, 'view')):
|
if actor._meta.model_name == 'user':
|
||||||
|
if actor.has_obj_perm(self.organization, 'view'):
|
||||||
|
return
|
||||||
|
|
||||||
|
requesting_user = kwargs.get('requesting_user', None)
|
||||||
|
if check_resource_server_for_user_in_organization(actor, self.organization, requesting_user):
|
||||||
|
return
|
||||||
|
|
||||||
raise ValidationError({'user': _('User must have view permission to Execution Environment organization')})
|
raise ValidationError({'user': _('User must have view permission to Execution Environment organization')})
|
||||||
|
|||||||
Reference in New Issue
Block a user